home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / unix / mvcprm11.1 < prev    next >
Internet Message Format  |  1989-05-10  |  76KB

  1. Path: xanth!ames!oliveb!sun!swap!page
  2. From: page%swap@Sun.COM (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i125:  mv/cp/rm - unix(tm)-like mv, cp, rm v1.1
  5. Message-ID: <104025@sun.Eng.Sun.COM>
  6. Date: 10 May 89 05:30:20 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 2763
  9. Approved: page@sun.com
  10.  
  11. Submitted-by: edwin@watcsc.waterloo.edu (Edwin Hoogerbeets)
  12. Posting-number: Volume 89, Issue 125
  13. Archive-name: unix/mv-cp-rm11.1
  14.  
  15. Move, copy, or remove files in the style of Unix mv/cp/rm.
  16.  
  17. [uuencoded executable included.  ..bob]
  18.  
  19. # This is a shell archive.
  20. # Remove anything above and including the cut line.
  21. # Then run the rest of the file through 'sh'.
  22. # Unpacked files will be owned by you and have default permissions.
  23. #----cut here-----cut here-----cut here-----cut here----#
  24. #!/bin/sh
  25. # shar: SHell ARchive
  26. # Run the following text through 'sh' to create:
  27. #    ReadMe
  28. #    makefile
  29. #    mv.c
  30. #    mv.uu
  31. #    mvtest.sh
  32. # This is archive 1 of a 1-part kit.
  33. # This archive created: Tue May  9 22:24:48 1989
  34. echo "extracting ReadMe"
  35. sed 's/^X//' << \SHAR_EOF > ReadMe
  36. X                 mv/cp/rm v1.1 - move, copy, or remove
  37. X                  files in the style of Unix mv/cp/rm
  38. X
  39. X                   Copyright 1989 Edwin Hoogerbeets
  40. X
  41. XThis code is freely redistributable as long as no charge other than
  42. Xreasonable copying fees is levied for it.
  43. X
  44. XUsage:
  45. X
  46. X    mv [-cfix]    [-] file1 file2
  47. X    mv [-cfix]    [-] path1 [path2 ...] dir
  48. X    cp [-fimnx]   [-] file1 file2
  49. X    cp [-fimnxrR] [-] path1 [path2 ...] dir
  50. X    rm [-cdfimrR] [-] path  [path ...]
  51. X
  52. X  Where path is either a file or a directory.
  53. X
  54. XOptions:
  55. X
  56. X    -c act like cp instead (as in "mv -c" means do a cp instead of mv)
  57. X
  58. X    -d remove directories only if they are empty (as in AmigaDOS Delete)
  59. X
  60. X    -f force quiet mode, overwriting destination files if necessary.
  61. X
  62. X    -i force interactive mode
  63. X
  64. X    -m act like mv instead
  65. X
  66. X    -n do not copy file dates, comments and protections (use "n"ew dates..)
  67. X
  68. X    -R same as -r
  69. X    -r recursively do directories as well (mv is always recursive)
  70. X
  71. X    -x act like rm instead (I ran out of option letters, that's why...)
  72. X
  73. X    -  end of options (useful to remove a file whose name starts with
  74. X       a dash eg. "-d")
  75. X
  76. X  Options f and i are mutually exclusive, with i taking precedence.
  77. X
  78. XNotes:
  79. X
  80. X  Yes, a three in one program! It slices, it dices, it even does
  81. X  julienne fries!
  82. X
  83. X  This version has the following features: [if I did not screw up :-]
  84. X
  85. X    - file permissions, dates, and comments are also copied or moved
  86. X      by default (switchable)
  87. X    - supports arp wildcarding, but does not insist on it (see below)
  88. X    - moves across volumes are supported
  89. X    - directories can be moved or copied recursively, even across
  90. X      volumes
  91. X    - attempts to allocate a big enough buffer to be able to copy
  92. X      or move files in one pass (reduces thrashing and increases speed)
  93. X    - does not print the bloody "foobar...copied" message for each file
  94. X      (which also increases speed)
  95. X    - can detect when two files are on the same volume (even if an
  96. X      assigned name is given) and uses Rename instead of copying
  97. X    - honours the delete bit
  98. X    - supports "" as current directory (eg. mv df1:* "")
  99. X
  100. X  This version has the following misfeatures:
  101. X
  102. X    - if a copy or move fails, it does not remove any files whatsoever
  103. X      (maybe it is a feature, I do not know)
  104. X    - all options are available to all forms of this program, though
  105. X      some are not used by some forms. (hence the usage information
  106. X      above) No checks are done for non-useful options.
  107. X
  108. X
  109. X  that maybe Manx specific. (I don't have Lattice, so I don't really
  110. X  know!)
  111. X
  112. X  The action performed depends on the executable's name. There are entries
  113. X  in the makefile to change the default name of the executables, if a
  114. X  different name is desired. Copy one executable to a different name to
  115. X  get a different action. The default action is to copy, since no files
  116. X  are removed and this is the least destructive option.
  117. X
  118. X  There is a small test script for the Dillon/Drew shell (easily ported to
  119. X  other shells) to test almost everything I can think of. If you can get
  120. X  cp/rm/mv to guru, or at least do something wierd, please send me a test
  121. X  case for the script and I will fix it pronto!
  122. X
  123. X  It is possible to get by with only one copy of the executable if you
  124. X  use a shell that supports aliases. The following aliases might be
  125. X  helpful:
  126. X
  127. X    alias cp mv -c           - mv is the single executable name
  128. X    alias rm mv -x           - x for remove. (makes sense, eh??)
  129. X    alias delete mv -xd      - act like AmigaDOS Delete command
  130. X    alias rmdir mv -xd       - remove directory a la unix
  131. X    alias mv Mv              - use the external mv/cp/rm command instead
  132. X    alias rm Rm                of the built in one!
  133. X    alias cp Cp
  134. X
  135. XWildcards:
  136. X
  137. X  Wildcards (arp) are supported at the request of Monsieur Dan Schein.
  138. X  To access them, there are appropriate spots in the makefile to define
  139. X  their use (using -DARP). The distribution binary was compiled with arp
  140. X  wildcarding.
  141. X
  142. X  If you do not have arp's programmers bindings, or if you do not wish to
  143. X  have wildcards, I have put in numerous [ugly-looking] #ifdef's throughout
  144. X  the code, so that it will compile without arp stuff as well. The
  145. X  executables I use do not have the wildcarding because I use Matt's
  146. X  (Drew Manxified) shell that expands the wildcards already.
  147. X
  148. XAcknowledgements:
  149. X
  150. X  If you thought your silly little example of Amiga programming is not
  151. X  worth publicly releasing, think again. This whole program is made of
  152. X  various hacked up examples, and has been very instructive for me to
  153. X  write! Please give out any examples you think could be remotely useful,
  154. X  as they probably are to someone. I hope that maybe this hack will be of
  155. X  use to someone as an example (even though it is a mess).
  156. X
  157. X  I would like to thank Matt Dillon (again) for his shell, from which
  158. X  I hacked the remove routines and the date setting routines.
  159. X  Thanks also to Chuck McManis for the GetVolume example from Fish 56.
  160. X  Thanks to Doug Tittle for the initial inspiration for this program.
  161. X  And finally, thanks to Rob Peck for his book, "Programmer's Guide to
  162. X  the Amiga" from which most of the know-how in this program was
  163. X  learned.
  164. X
  165. XFiles:
  166. X
  167. X ReadMe                    rwed    6392   13  27-Apr-89 22:01:43
  168. X cp                        rwed   13864   28  27-Apr-89 21:53:41
  169. X makefile                 arwed    1099    3  23-Apr-89 21:56:40
  170. X mv.c                     arwed   39338   78  24-Apr-89 00:30:35
  171. X mvtest.sh                arwed    5812   12  23-Apr-89 22:09:09
  172. X139 Blocks, 66505 Bytes used in 5 files
  173. X
  174. XRevision History:
  175. X
  176. X1.1
  177. X  - added in c, m and x options to allow one executable and different
  178. X    actions using a shell's alias mechanism. (ie. alias cp mv -c)
  179. X  - added d option to remove directories but only if they are empty
  180. X    (as in the behaviour of AmigaDOS Delete)
  181. X  - fixed problem with copying 0 byte files
  182. X  - fixed problem with moving a file to itself with different
  183. X    capitalization (mv foo Foo)
  184. X  - detects much better if there is an attempt to copy a file to itself
  185. X  - uses *much* less stack space (major problem with 1.0)
  186. X  - somewhat smaller size (but now Manx dependant...)
  187. X
  188. X1.0
  189. X  - initial effort
  190. X
  191. XPlease redirect any comments, criticisms or spare Swimsuit Issues
  192. Xof Sports Illustrated to:
  193. X
  194. XEdwin Hoogerbeets
  195. XUsenet: edwin@watcsc.waterloo.edu (May '89 to Aug '89)
  196. XCIS:    72647,3675                (any time at all)
  197. X
  198. X
  199. X
  200. X
  201. SHAR_EOF
  202. echo "extracting makefile"
  203. sed 's/^X//' << \SHAR_EOF > makefile
  204. X#
  205. X# makefile for mv v1.0 - Unix-like move file utility
  206. X#
  207. X# Copyright 1989 Edwin Hoogerbeets
  208. X#
  209. X# This code may be freely redistributed as long as no charges other than
  210. X# reasonable copying fees are levied for it.
  211. X#
  212. X
  213. X#
  214. X# Set these to the executable names you want.
  215. X#
  216. XMVNAME=mv
  217. XCPNAME=cp
  218. XRMNAME=rm
  219. X
  220. X# destination of the executables
  221. XDESTDIR=c:
  222. X
  223. X#
  224. X# Set this to -DARP and -la32 to include arp wildcarding
  225. X#
  226. XARP=-DARP
  227. XARPLIB=-la32
  228. X
  229. X#
  230. X# Set this to -g for sdb
  231. X#
  232. XLNDEBUG=
  233. X#-g
  234. X
  235. X#
  236. X# Add -DDEBUG and -n for verbose debugging and sdb
  237. X#
  238. XDEBUG=
  239. X#-n
  240. X#-DDEBUG
  241. X
  242. XCFLAGS=+L $(DEBUG) $(ARP) -DMVNAME="$(MVNAME)" -DCPNAME="$(CPNAME)" \
  243. X-DRMNAME="$(RMNAME)"
  244. X
  245. X#
  246. X# do copy first, so we can use it to copy itself, instead of relinking!
  247. X#
  248. Xall: $(CPNAME) $(RMNAME) $(MVNAME)
  249. X
  250. X$(CPNAME): mv.o
  251. X    ln $(LNDEBUG) mv.o $(ARPLIB) -lc32 -o $@
  252. X
  253. X$(MVNAME): $(CPNAME)
  254. X    $(CPNAME) $(CPNAME) $@
  255. X
  256. X$(RMNAME): $(CPNAME)
  257. X    $(CPNAME) $(CPNAME) $@
  258. X
  259. Xclean:
  260. X    $(RMNAME) -f $(CPNAME) $(MVNAME) $(RMNAME) $(CPNAME).dbg \
  261. X$(RMNAME).dbg $(MVNAME).dbg mv.o
  262. X
  263. Xmv.o: mv.c
  264. X
  265. Xinstall: all
  266. X    $(CPNAME) -f $(CPNAME) $(RMNAME) $(MVNAME) $(DESTDIR)
  267. X
  268. X
  269. X
  270. SHAR_EOF
  271. echo "extracting mv.c"
  272. sed 's/^X//' << \SHAR_EOF > mv.c
  273. X/*
  274. X * mv v1.0 - Unix-like move file utility
  275. X *
  276. X * Copyright 1989 Edwin Hoogerbeets
  277. X *
  278. X * This code may be freely redistributed as long as no charges other than
  279. X * reasonable copying fees are levied for it.
  280. X *
  281. X * Manx version by Edwin Hoogerbeets
  282. X * usenet: edwin@watcsc.waterloo.edu
  283. X * CIS:    72647,3675
  284. X *
  285. X * Works mostly like the Unix move.
  286. X *
  287. X * Usage: mv [-cfix]    [-] file1 file2
  288. X *        mv [-cfix]    [-] path1 [path2 ...] dir
  289. X *        cp [-fimnx]   [-] file1 file2
  290. X *        cp [-fimnxrR] [-] path1 [path2 ...] dir
  291. X *        rm [-cdfimrR] [-] path  [path ...]
  292. X *
  293. X * Where path is either a file or a directory.
  294. X *
  295. X *  -c act like cp instead (as in "mv -c" means do a cp instead of mv)
  296. X *  -d remove directories only if they are empty (as in AmigaDOS Delete)
  297. X *  -f force quiet mode, overwriting destination files if necessary.
  298. X *  -i force interactive mode
  299. X *  -m act like mv instead
  300. X *  -n do not copy file dates, comments and protections (use "n"ew dates..)
  301. X *  -R same as -r
  302. X *  -r recursively do directories as well (mv is always recursive)
  303. X *  -x act like rm instead
  304. X *  -  end of options (useful to remove a file whose name starts with
  305. X *     a dash eg. "-d")
  306. X *
  307. X * Moves, etc. across devices are supported.
  308. X *
  309. X */
  310. X
  311. X#include <fcntl.h>
  312. X#include <libraries/dos.h>
  313. X#include <libraries/dosextens.h>
  314. X#ifdef ARP
  315. X#include <libraries/arpbase.h>
  316. X#include <libraries/arpfunc.h>
  317. X#endif
  318. X#include <exec/memory.h>
  319. X#include <ctype.h>
  320. X
  321. X#define FIBSIZE (long)sizeof(struct FileInfoBlock)
  322. X#define BUFSIZE 256
  323. X
  324. Xtypedef struct fl {
  325. X  char name[BUFSIZE];
  326. X  struct fl *next;
  327. X} filenode;
  328. X
  329. X#define FNSIZE (long)sizeof(filenode)
  330. X
  331. Xstruct FileLock          *lock;
  332. Xstruct FileInfoBlock     *fib;
  333. X
  334. Xint mvflag = 0, /* is this a move command? */
  335. X    cpflag = 0, /* is this a copy command? */
  336. X    rmflag = 0, /* is this a remove command? */
  337. X    rflag  = 0, /* is this command recursive? */
  338. X    fflag  = 0, /* don't ask if it should overwrite, just do it */
  339. X    iflag  = 0, /* do interactive mode */
  340. X    nflag  = 1, /* copy file dates, comments and protections */
  341. X    dflag  = 0; /* delete directories only if they are empty */
  342. X
  343. Xchar commandname[32] = "";
  344. X
  345. Xlong ofile;     /* output file handle */
  346. Xlong ifile;     /* input file handle  */
  347. X
  348. X#ifdef ARP
  349. X
  350. Xtypedef struct BAP {
  351. X  struct AnchorPath bap_ap;
  352. X  char padding[BUFSIZE];
  353. X} BigAnchorPath;
  354. X
  355. X#define APSIZE (long)sizeof(BigAnchorPath)
  356. X
  357. Xint arpflag = 0;
  358. X
  359. X#endif
  360. X
  361. X/* these are so Manx won't complain about ptr/int conversions, etc. */
  362. Xextern struct FileLock   *ParentDir();
  363. Xextern struct FileLock   *CreateDir();
  364. Xextern struct FileLock   *Lock();
  365. Xextern struct FileLock   *CurrentDir();
  366. Xextern int                Examine();
  367. Xextern char              *AllocMem();
  368. Xextern struct FileHandle *Open();
  369. Xextern struct MsgPort    *DeviceProc();
  370. Xextern struct Library    *OpenLibrary();
  371. Xextern struct _dev       *_devtab;
  372. X
  373. X#ifdef ARP
  374. Xstruct ArpBase       *ArpBase;
  375. Xstruct IntuitionBase *IntuitionBase;
  376. Xstruct GfxBase       *GfxBase;
  377. X#endif
  378. X
  379. X#include <exec/alerts.h>
  380. X#include <workbench/startup.h>
  381. X
  382. Xextern long _savsp, _stkbase;
  383. X
  384. Xextern int errno;
  385. Xextern int Enable_Abort;
  386. X
  387. Xextern int _argc, _arg_len;
  388. Xextern char **_argv, *_arg_lin;
  389. X
  390. X_main(alen, aptr)
  391. Xlong alen;
  392. Xchar *aptr;
  393. X{
  394. X        struct Process *pp, *FindTask();
  395. X
  396. X        _stkbase = _savsp - *((long *)_savsp+1) + 8;
  397. X        *(long *)_stkbase = 0x4d414e58L;
  398. X
  399. X        pp = FindTask(0L);
  400. X        _cli_parse(pp, alen, aptr);
  401. X        Enable_Abort = 1;
  402. X
  403. X        exit(main(_argc, _argv));
  404. X}
  405. X
  406. X/*
  407. X * The following few routines were taken from my edlib1.1 source. They
  408. X * are included here so that anyone can recompile this source without
  409. X * the library. (I'll be happy to send you edlib if you want it.)
  410. X */
  411. X
  412. Xchar *strrpbrk(str, charset)
  413. Xregister char *str, *charset;
  414. X{
  415. X  register char *temp;
  416. X  extern char *index();
  417. X
  418. X  temp = str + strlen(str) - 1;
  419. X
  420. X  while ( temp != (str - 1)  && !index(charset, *temp) )
  421. X    --temp;
  422. X
  423. X  return( (temp != (str - 1)) ? temp : NULL);
  424. X}
  425. X
  426. Xint stricmp(str1,str2)
  427. Xregister char *str1,*str2;
  428. X{
  429. X    register int index = 0;
  430. X
  431. X    while ( str1[index] && str2[index] &&
  432. X            tolower(str1[index]) == tolower(str2[index]) )
  433. X        ++index;
  434. X
  435. X    return( (tolower(str1[index]) < tolower(str2[index])) ? -1 :
  436. X          ( (tolower(str1[index]) > tolower(str2[index])) ?  1 : 0) );
  437. X}
  438. X
  439. X
  440. X/* return a pointer to the first character of a file name in a path name */
  441. Xchar *basename(buf)
  442. Xregister char *buf;
  443. X{
  444. X  register char *foo = strrpbrk(buf,":/");
  445. X
  446. X  return( foo ? (foo + 1) : buf );
  447. X}
  448. X
  449. X/* end of edlib routines */
  450. X
  451. X/* write out a string */
  452. Xint emit(file,str)
  453. Xlong file;
  454. Xchar *str;
  455. X{
  456. X  Write(file,str,strlen(str));
  457. X}
  458. X
  459. X/*
  460. X * return the length of the largest piece of memory that is possibly
  461. X * contiguous
  462. X */
  463. Xlong mem()
  464. X{
  465. X   long chip, fast;
  466. X   extern long AvailMem();
  467. X
  468. X   Forbid();
  469. X   chip = AvailMem(MEMF_CHIP);
  470. X   fast = AvailMem(MEMF_FAST);
  471. X   Permit();
  472. X
  473. X   return(chip>fast ? chip : fast);
  474. X}
  475. X
  476. X/* make a new file info block and return a pointer to it */
  477. Xstruct FileInfoBlock *newfib()
  478. X{
  479. X  struct FileInfoBlock *fib;
  480. X
  481. X  fib = (struct FileInfoBlock *) AllocMem(FIBSIZE, MEMF_CLEAR);
  482. X
  483. X  if ( !fib ) {
  484. X    if ( !fflag ) {
  485. X      emit(ofile,commandname);
  486. X      emit(ofile,": Out of memory!\n");
  487. X    }
  488. X    return(NULL);
  489. X  }
  490. X
  491. X  return(fib);
  492. X}
  493. X
  494. X/* get rid of a used file info block */
  495. Xint freefib(fib)
  496. X{
  497. X  if ( fib )
  498. X    FreeMem(fib,FIBSIZE);
  499. X}
  500. X
  501. X/* make a new buffer and return a pointer to it */
  502. Xchar *newbuf()
  503. X{
  504. X  register char *temp = AllocMem(BUFSIZE,MEMF_CLEAR|MEMF_PUBLIC);
  505. X
  506. X  if ( !temp ) {
  507. X    if ( !fflag ) {
  508. X      emit(ofile,commandname);
  509. X      emit(ofile,": Out of memory!\n");
  510. X    }
  511. X    return(NULL);
  512. X  }
  513. X
  514. X  return(temp);
  515. X}
  516. X
  517. X/* free a buffer previously allocated with newbuf() */
  518. Xint freebuf(buf)
  519. Xchar *buf;
  520. X{
  521. X  if ( buf ) {
  522. X    FreeMem(buf,BUFSIZE);
  523. X  }
  524. X}
  525. X
  526. X/* make a new filenode structure and return a pointer to it */
  527. Xfilenode *newfilenode()
  528. X{
  529. X  filenode *new = (filenode *)
  530. X    AllocMem(FNSIZE,MEMF_PUBLIC|MEMF_CLEAR);
  531. X
  532. X  if ( new ) {
  533. X    new->name[0] = '\0';
  534. X    new->next = NULL;
  535. X  }
  536. X
  537. X  return(new);
  538. X}
  539. X
  540. X/* free a list of filenode structures */
  541. Xint freefilenodes(file)
  542. Xfilenode *file;
  543. X{
  544. X  if ( file ) {
  545. X    freefilenodes(file->next);
  546. X
  547. X    FreeMem(file,FNSIZE);
  548. X  }
  549. X}
  550. X
  551. X/* return a pointer to the last element of a filenode list */
  552. Xfilenode *end(file)
  553. Xfilenode *file;
  554. X{
  555. X  if ( file ) {
  556. X    if ( file->next ) {
  557. X      return(end(file->next));
  558. X    } else {
  559. X      return(file);
  560. X    }
  561. X  } else {
  562. X    return(NULL);
  563. X  }
  564. X}
  565. X
  566. X/* return the length of a list of filenodes */
  567. Xint arglength(file)
  568. Xfilenode *file;
  569. X{
  570. X  if ( file->next ) {
  571. X    return(arglength(file->next)+1);
  572. X  } else {
  573. X    return(1);
  574. X  }
  575. X}
  576. X
  577. X/* Does the input string contain a wildcard? */
  578. Xint haswild(name)
  579. Xchar *name;
  580. X{
  581. X  register int foo = 0;
  582. X
  583. X  while ( name[foo] && name[foo] != '*' && name[foo] != '?' &&
  584. X          name[foo] != '#' )
  585. X    ++foo;
  586. X
  587. X  return ( name[foo] );
  588. X}
  589. X
  590. X
  591. X/*
  592. X * This routine takes a string with possibly a wildcard in it and expands
  593. X * it to a list of filenode structures. If arp isn't opened or if it
  594. X * wasn't compiled with arp, then it creates a list of 1 filenode containing
  595. X * the argument it was passed. The pointer to nomem is where it puts the
  596. X * error code for "low on available memory" errors.
  597. X */
  598. Xfilenode *expand(name,nomem)
  599. Xchar *name;
  600. Xint *nomem;
  601. X{
  602. X  filenode *file;
  603. X
  604. X# ifdef ARP
  605. X  if ( arpflag && haswild(name) ) {
  606. X    filenode *temp;
  607. X    int error;
  608. X    BigAnchorPath *anchor;
  609. X
  610. X    *nomem = 0;
  611. X
  612. X    anchor = (BigAnchorPath *)
  613. X        AllocMem(APSIZE,MEMF_CLEAR|MEMF_PUBLIC);
  614. X
  615. X    anchor->bap_ap.ap_Length = BUFSIZE;
  616. X
  617. X    if ( FindFirst(name,anchor) ) {
  618. X      FreeAnchorChain(anchor);
  619. X      return(NULL);
  620. X    }
  621. X
  622. X    if ( file = newfilenode() ) {
  623. X      strcat(file->name,anchor->bap_ap.ap_Buf);
  624. X    } else {
  625. X      *nomem = 1;
  626. X      FreeAnchorChain(anchor);
  627. X      return(NULL);
  628. X    }
  629. X#   ifdef DEBUG
  630. X    printf("First matched file: %s\n",file->name);
  631. X#   endif
  632. X
  633. X    temp = file;
  634. X
  635. X    while ( !(error = FindNext(anchor)) ) {
  636. X
  637. X      if ( !(temp->next = newfilenode()) ) {
  638. X        *nomem = 1;
  639. X        FreeAnchorChain(anchor);
  640. X        freefilenodes(file);
  641. X        return(NULL);
  642. X      }
  643. X
  644. X      temp = temp->next;
  645. X
  646. X      strcat(temp->name,anchor->bap_ap.ap_Buf);
  647. X
  648. X#   ifdef DEBUG
  649. X    printf("Next matched file: %s\n",temp->name);
  650. X#   endif
  651. X    }
  652. X
  653. X    FreeAnchorChain(anchor);
  654. X  } else {
  655. X# endif
  656. X    file = newfilenode();
  657. X
  658. X    if ( file ) {
  659. X      *nomem = 0;
  660. X      strcat(file->name,name);
  661. X    } else {
  662. X      *nomem = 1;
  663. X      return(NULL);
  664. X    }
  665. X
  666. X# ifdef ARP
  667. X  }
  668. X# endif
  669. X
  670. X  return(file);
  671. X}
  672. X
  673. X/* well, I guess this is a pro-choice program. ;-) */
  674. X_abort()
  675. X{
  676. X  if ( lock )
  677. X    UnLock(lock);
  678. X
  679. X  exit(-1);
  680. X}
  681. X
  682. X/*
  683. X * make a string containing the path part of a full AmigaDOS path name.
  684. X * return a pointer to this string.
  685. X */
  686. Xchar *parent(name)
  687. Xchar *name;
  688. X{
  689. X  register char *foo;
  690. X  char *temp = AllocMem((long)strlen(name)+1,MEMF_CLEAR);
  691. X
  692. X  strcat(temp,name);
  693. X
  694. X  /* get a pointer to the filename part */
  695. X  foo = basename(temp);
  696. X
  697. X  /*
  698. X   * lop off the file name part -- the length of the whole original
  699. X   * string must still be freed when freeing what temp points to.
  700. X   */
  701. X  *foo = '\0';
  702. X
  703. X  return(temp);
  704. X}
  705. X
  706. X/* are the two files on the same volume? If you can't tell, guess */
  707. Xint samedev(src,dst)
  708. Xchar *src, *dst;
  709. X{
  710. X  char  srcbuf[40], dstbuf[40], *temp;
  711. X  struct FileLock *lock;
  712. X
  713. X  /* Simultaneous get a lock and convert BPTR to a C pointer */
  714. X  lock = (struct FileLock *)BADDR(Lock(src,ACCESS_READ));
  715. X
  716. X  if (lock == NULL) {
  717. X    return(-1);
  718. X  }
  719. X
  720. X  temp = (char *)
  721. X    BADDR(((struct DeviceList *)BADDR(lock->fl_Volume))->dl_Name);
  722. X
  723. X  strncpy(srcbuf,&temp[1],temp[0]+1);
  724. X  srcbuf[temp[0]+2] = '\0';
  725. X
  726. X  UnLock(((long)lock) >> 2);  /* You must UnLock or the GURU visits */
  727. X
  728. X  temp = parent(dst);
  729. X
  730. X  lock = (struct FileLock *)BADDR(Lock(temp,ACCESS_READ));
  731. X
  732. X  FreeMem(temp,strlen(dst)+1);
  733. X
  734. X  if (lock == NULL) {
  735. X    return(-1);
  736. X  }
  737. X
  738. X  temp = (char *)
  739. X    BADDR(((struct DeviceList *)BADDR(lock->fl_Volume))->dl_Name);
  740. X
  741. X  strncpy(dstbuf,&temp[1],temp[0]+1);
  742. X  dstbuf[temp[0]+2] = '\0';
  743. X
  744. X  UnLock(((long)lock) >> 2);  /* You must UnLock or the GURU visits */
  745. X
  746. X# ifdef DEBUG
  747. X  printf("%s and %s are %son the same volume\n",src,dst,
  748. X        (!stricmp(srcbuf,dstbuf))?"":"not ");
  749. X# endif
  750. X  return( !stricmp(srcbuf,dstbuf) );
  751. X}
  752. X
  753. X/*
  754. X * Is the named file a directory? Get a File Info Block and point fib to
  755. X * it and return the results.
  756. X *
  757. X * return   0  for not a dir (ie. file)
  758. X * return   1  for a dir
  759. X * return   2  for no access to file
  760. X * return   3  for not being able to examine file
  761. X *
  762. X */
  763. Xint isdir(path,fib)
  764. Xchar *path;
  765. Xstruct FileInfoBlock **fib;
  766. X{
  767. X  struct FileLock *lock;
  768. X  register int result;
  769. X
  770. X  /* allocate a word aligned memory block to hold our info */
  771. X  *fib = newfib();
  772. X
  773. X  if ( !(lock = Lock(path,ACCESS_READ)) ) {
  774. X    return(2);
  775. X  }
  776. X
  777. X  if ( *fib ) {
  778. X    if ( Examine(lock,*fib) ) {
  779. X
  780. X      /* if the source is not a directory .. */
  781. X      result = (*fib)->fib_DirEntryType > 0 ? 1 : 0;
  782. X
  783. X    } else {
  784. X      /* 3 for could not examine */
  785. X      result = 3;
  786. X    }
  787. X
  788. X  } else {
  789. X    if ( !fflag ) {
  790. X      emit(ofile,commandname);
  791. X      emit(ofile,": Out of memory!\n");
  792. X    }
  793. X    UnLock(lock);
  794. X    return(-1);
  795. X  }
  796. X
  797. X  UnLock(lock);
  798. X
  799. X  return(result);
  800. X}
  801. X
  802. X#ifdef ARP
  803. Xvoid closethings()
  804. X{
  805. X  if ( ArpBase ) {
  806. X    CloseLibrary(ArpBase);
  807. X  }
  808. X
  809. X  if ( IntuitionBase ) {
  810. X    CloseLibrary(IntuitionBase);
  811. X  }
  812. X
  813. X  if ( GfxBase ) {
  814. X    CloseLibrary(GfxBase);
  815. X  }
  816. X
  817. X}
  818. X#endif
  819. X
  820. Xvoid usage()
  821. X{
  822. X  if ( !fflag ) {
  823. X    emit(ofile,"Usage: mv [-cfix]    [-] file1 file2\n");
  824. X    emit(ofile,"       mv [-cfix]    [-] path1 [path2 ...] dir\n");
  825. X    emit(ofile,"       cp [-fimnx]   [-] file1 file2\n");
  826. X    emit(ofile,"       cp [-fimnxrR] [-] path1 [path2 ...] dir\n");
  827. X    emit(ofile,"       rm [-cdfimrR] [-] path  [path ...]\n");
  828. X    emit(ofile,"\nWhere path is either a file or a directory.\n");
  829. X  }
  830. X
  831. X# ifdef ARP
  832. X  closethings();
  833. X# endif
  834. X
  835. X  exit(1);
  836. X}
  837. X
  838. X/* the following is a mess. brace yourself. */
  839. Xmain(argc,argv)
  840. Xint argc;
  841. Xchar *argv[];
  842. X{
  843. X  register int index, c;
  844. X  struct FileInfoBlock *startfib = NULL, *endfib = NULL;
  845. X  filenode *start = NULL, *temp = NULL, *endnode = NULL;
  846. X  int args, result, nomem;
  847. X
  848. X  ofile = (long) Open("*",MODE_NEWFILE); /* open new file for stderr */
  849. X  ifile = Input();
  850. X
  851. X# ifdef ARP
  852. X  ArpBase = (struct ArpBase *) OpenLibrary(ArpName,0L);
  853. X
  854. X  if ( ArpBase ) {
  855. X#   ifdef DEBUG
  856. X    printf("opened arp.library okay\n");
  857. X#   endif
  858. X
  859. X    if ( !(IntuitionBase = (struct IntuitionBase *)
  860. X           OpenLibrary("intuition.library",0L)) ) {
  861. X      emit(ofile,"Could not open intuition.library\n");
  862. X#     ifdef ARP
  863. X      closethings();
  864. X#     endif
  865. X      exit(-1);
  866. X    }
  867. X
  868. X    if ( !(GfxBase = (struct GfxBase *)
  869. X           OpenLibrary("graphics.library",0L)) ) {
  870. X      emit(ofile,"Could not open graphics.library\n");
  871. X#     ifdef ARP
  872. X      closethings();
  873. X#     endif
  874. X      exit(-1);
  875. X    }
  876. X    arpflag = 1;
  877. X  } else {
  878. X#   ifdef DEBUG
  879. X    printf("Arp.library not opened.\n");
  880. X#   endif
  881. X    arpflag = 0;
  882. X  }
  883. X# endif
  884. X
  885. X  if ( !stricmp(basename(argv[0]),MVNAME) ) {
  886. X
  887. X    ++mvflag;
  888. X    ++rflag;
  889. X
  890. X  } else if ( !stricmp(basename(argv[0]),RMNAME) ) {
  891. X
  892. X    ++rmflag;
  893. X
  894. X  } else {
  895. X
  896. X    /*
  897. X     * default to the copy command so that if the user renames the
  898. X     * executable to something we don't understand, we don't do
  899. X     * anything really destructive.
  900. X     */
  901. X    ++cpflag;
  902. X  }
  903. X
  904. X  index = 1;
  905. X
  906. X  /* simplistic argument processing */
  907. X
  908. X  while ( argv[index][0] == '-' ) {
  909. X    c = 1;
  910. X
  911. X    /* - option was specified to end other options */
  912. X    if ( !argv[index][c] ) {
  913. X      ++index;
  914. X      break;
  915. X    }
  916. X
  917. X    while ( argv[index][c] ) {
  918. X      switch ( argv[index][c] ) {
  919. X        case 'c':
  920. X          cpflag = 1;
  921. X          rflag = mvflag = rmflag = 0;
  922. X          break;
  923. X
  924. X        case 'd':
  925. X          dflag = 1;
  926. X          break;
  927. X
  928. X        case 'f':
  929. X          fflag = 1;
  930. X          iflag = 0;
  931. X          break;
  932. X
  933. X        case 'i':
  934. X          fflag = 0;
  935. X          iflag = 1;
  936. X          break;
  937. X
  938. X        case 'm':
  939. X          rflag = mvflag = 1;
  940. X          cpflag = rmflag = 0;
  941. X          break;
  942. X
  943. X        case 'n':
  944. X          nflag = 0;
  945. X          break;
  946. X
  947. X        case 'R':
  948. X        case 'r':
  949. X          rflag = 1;
  950. X          break;
  951. X
  952. X        case 'x':
  953. X          rmflag = 1;
  954. X          rflag = mvflag = cpflag = 0;
  955. X          break;
  956. X
  957. X        default:
  958. X          emit(ofile,"invalid option ");
  959. X          Write(ofile,&argv[index][c],1);
  960. X          emit(ofile,"\n");
  961. X          usage();
  962. X      }
  963. X      c++;
  964. X    }
  965. X    ++index;
  966. X  }
  967. X
  968. X  /* if there are no file names left after the options were processed ... */
  969. X  if ( (argc - index) < (rmflag ? 1 : 2) ) {
  970. X    usage();
  971. X  }
  972. X
  973. X  if ( mvflag ) {
  974. X
  975. X    strcat(commandname,MVNAME);
  976. X#   ifdef DEBUG
  977. X    printf("mv command executing\n");
  978. X#   endif
  979. X
  980. X  } else if ( rmflag ) {
  981. X
  982. X    strcat(commandname,RMNAME);
  983. X#   ifdef DEBUG
  984. X    printf("rm command executing\n");
  985. X#   endif
  986. X
  987. X  } else {
  988. X
  989. X    strcat(commandname,CPNAME);
  990. X#   ifdef DEBUG
  991. X    printf("cp command executing\n");
  992. X#   endif
  993. X
  994. X  }
  995. X
  996. X  /*
  997. X   * expand the first argument. index contains the number of the first
  998. X   * file name argument at this point, because it is updated by the options
  999. X   * parsing piece of code above.
  1000. X   */
  1001. X  start = expand(argv[index++],&nomem);
  1002. X
  1003. X  if ( nomem ) {
  1004. X    if ( !fflag ) {
  1005. X      emit(ofile,commandname);
  1006. X      emit(ofile,": Out of memory!\n");
  1007. X    }
  1008. X#   ifdef ARP
  1009. X    closethings();
  1010. X#   endif
  1011. X    exit(-1);
  1012. X  }
  1013. X
  1014. X  temp = end(start);
  1015. X
  1016. X  for ( ;index < argc; index++) {
  1017. X
  1018. X    /*
  1019. X     * it is possible that previous arguments had a wildcard and didn't
  1020. X     * match anything, so temp would be NULL at this point, otherwise
  1021. X     * attach the new file list from expand onto the end of the list.
  1022. X     */
  1023. X    if ( temp ) {
  1024. X      temp->next = expand(argv[index],&nomem);
  1025. X    } else {
  1026. X      temp = expand(argv[index],&nomem);
  1027. X      start = temp;
  1028. X    }
  1029. X
  1030. X    if ( nomem ) {
  1031. X      if ( !fflag ) {
  1032. X        emit(ofile,commandname);
  1033. X        emit(ofile,": Out of memory!\n");
  1034. X      }
  1035. X#     ifdef ARP
  1036. X      closethings();
  1037. X#     endif
  1038. X      freefilenodes(start);
  1039. X      exit(-1);
  1040. X    }
  1041. X
  1042. X    temp = end(temp);
  1043. X  }
  1044. X
  1045. X  endnode = end(start);
  1046. X  args = arglength(start);
  1047. X
  1048. X# ifdef DEBUG
  1049. X  printf("argc: %d\n",argc);
  1050. X
  1051. X  for ( temp = start; temp; temp = temp->next ) {
  1052. X    printf("argument \"%s\"\n", temp->name );
  1053. X  }
  1054. X# endif
  1055. X
  1056. X  if ( !rmflag ) {
  1057. X
  1058. X    /*
  1059. X     * main case statement for the program to find out what to do with
  1060. X     * its life. (You gotta fight, for your right,
  1061. X     * to PPPPPAAAAAAARRRRRRRRIIIIIIIITTTTTTTYYYYYY!!!!!!
  1062. X     */
  1063. X
  1064. X    /*
  1065. X     * check last argument (ie. the destination file) to make sure it
  1066. X     * is a directory
  1067. X     */
  1068. X    switch ( isdir(endnode->name,&endfib) ) {
  1069. X
  1070. X      /*
  1071. X       * destination is a file, check that there are only 2 arguments
  1072. X       * and that the first one is also a file, or inform the user
  1073. X       * of his (or her) silliness.
  1074. X       */
  1075. X      case 0:
  1076. X        if ( args == 2 ) {
  1077. X          if ( isdir(start->name,&startfib) ) {
  1078. X            if ( !fflag ) {
  1079. X              emit(ofile,commandname);
  1080. X              emit(ofile,": cannot move a directory onto a file\n");
  1081. X            }
  1082. X
  1083. X            freefib(startfib);
  1084. X            freefib(endfib);
  1085. X            freefilenodes(start);
  1086. X            usage();
  1087. X
  1088. X          } else {
  1089. X
  1090. X            result = mv2f(start->name,startfib,endnode->name,endfib);
  1091. X
  1092. X            if ( result == 2 && mvflag ) {
  1093. X              rm(start->name,fflag,iflag);
  1094. X            }
  1095. X
  1096. X            freefib(startfib);
  1097. X            freefib(endfib);
  1098. X            freefilenodes(start);
  1099. X            exit(0);
  1100. X          }
  1101. X        } else {
  1102. X          if ( !fflag ) {
  1103. X            emit(ofile,commandname);
  1104. X            emit(ofile,": cannot move a directory onto a file\n");
  1105. X          }
  1106. X          freefib(endfib);
  1107. X          freefilenodes(start);
  1108. X          usage();
  1109. X        }
  1110. X        break;
  1111. X
  1112. X      /* destination is a directory */
  1113. X      case 1:
  1114. X        freefib(endfib);
  1115. X        break;
  1116. X
  1117. X      /* destination doesn't exist */
  1118. X      case 2:
  1119. X        if ( args == 2 && !isdir(start->name,&startfib) ) {
  1120. X
  1121. X          /*
  1122. X           * move file specified in start->name to a new
  1123. X           * file in endnode->name
  1124. X           */
  1125. X          result = mv2f(start->name,startfib,endnode->name,NULL);
  1126. X
  1127. X          if ( result == 2 && mvflag ) {
  1128. X            rm(start->name,fflag,iflag);
  1129. X          }
  1130. X
  1131. X          freefib(endfib);
  1132. X          freefib(startfib);
  1133. X          freefilenodes(start);
  1134. X          exit(0);
  1135. X        } else {
  1136. X          if ( args > 2 ) {
  1137. X            struct FileLock *lock;
  1138. X            char *buf = newbuf();
  1139. X
  1140. X            freefib(startfib);
  1141. X            freefib(endfib);
  1142. X
  1143. X            if ( !buf ) {
  1144. X              freefilenodes(start);
  1145. X              exit(-1);
  1146. X            }
  1147. X
  1148. X            if ( iflag ) {
  1149. X              buf[0] = '\0';
  1150. X              emit(ofile,commandname);
  1151. X              emit(ofile,": create directory ");
  1152. X              emit(ofile,endnode->name);
  1153. X
  1154. X              Read(ifile,buf,BUFSIZE);
  1155. X
  1156. X              if ( buf[0] != 'y' && buf[0] != 'Y' ) {
  1157. X                break;
  1158. X              }
  1159. X            }
  1160. X
  1161. X            if ( !(lock = CreateDir(endnode->name)) ) {
  1162. X              if ( !fflag ) {
  1163. X                emit(ofile,commandname);
  1164. X                emit(ofile,": unable to create directory ");
  1165. X                emit(ofile,endnode->name);
  1166. X                emit(ofile,"\n");
  1167. X              }
  1168. X#             ifdef ARP
  1169. X              closethings();
  1170. X#             endif
  1171. X              freefilenodes(start);
  1172. X              freebuf(buf);
  1173. X              exit(-1);
  1174. X            } else {
  1175. X              UnLock(lock);
  1176. X            }
  1177. X            freebuf(buf);
  1178. X          }
  1179. X        }
  1180. X        break;
  1181. X
  1182. X      case 3:
  1183. X        if ( !fflag ) {
  1184. X          emit(ofile,commandname);
  1185. X          emit(ofile,": could not examine file ");
  1186. X          emit(ofile,endnode->name);
  1187. X          emit(ofile,"\n");
  1188. X        }
  1189. X
  1190. X        freefilenodes(start);
  1191. X        freefib(endfib);
  1192. X        exit(3);
  1193. X        break;
  1194. X    }
  1195. X
  1196. X# ifdef DEBUG
  1197. X  printf("Move or copy files to directory %s\n",endnode->name);
  1198. X# endif
  1199. X  }
  1200. X
  1201. X  /*
  1202. X   * For each source argument, move it to the correct directory.
  1203. X   */
  1204. X  for ( temp = start; temp; temp = temp->next ) {
  1205. X
  1206. X    Chk_Abort();
  1207. X
  1208. X    if ( (temp != endnode) && (mvflag || cpflag) ) {
  1209. X      result = mv(temp->name,endnode->name);
  1210. X
  1211. X      switch ( result ) {
  1212. X
  1213. X        /* if there was an error, get out now */
  1214. X        case -1:
  1215. X#         ifdef ARP
  1216. X          closethings();
  1217. X#         endif
  1218. X          freefilenodes(start);
  1219. X          exit(-1);
  1220. X
  1221. X        /* if there was a successful copy, then remove the source */
  1222. X        case 2:
  1223. X          if ( !cpflag )
  1224. X            rm(temp->name,fflag,iflag);
  1225. X          break;
  1226. X
  1227. X        /*
  1228. X         * if there was a successful move, then do nothing, 'cause the
  1229. X         * source is gone already.
  1230. X         */
  1231. X        default:
  1232. X          break;
  1233. X      }
  1234. X    } else if ( rmflag ) {
  1235. X      rm(temp->name,fflag,iflag);
  1236. X    }
  1237. X  }
  1238. X
  1239. X# ifdef ARP
  1240. X  closethings();
  1241. X# endif
  1242. X
  1243. X  freefilenodes(start);
  1244. X
  1245. X  exit(0);
  1246. X}
  1247. X
  1248. Xint rm_file(file,fflag,iflag)
  1249. Xchar *file;
  1250. Xint fflag, iflag;
  1251. X{
  1252. X  register int result;
  1253. X  char *buf = newbuf();
  1254. X
  1255. X  if ( !buf ) {
  1256. X    return(-1);
  1257. X  }
  1258. X
  1259. X# ifdef DEBUG
  1260. X  printf("Deleting file %s\n",file);
  1261. X# endif
  1262. X
  1263. X  switch ( isdeletable(file) ) {
  1264. X    case 2:
  1265. X      if ( !fflag ) {
  1266. X        emit(ofile,commandname);
  1267. X        emit(ofile,": could not find file ");
  1268. X        emit(ofile,file);
  1269. X        emit(ofile,"\n");
  1270. X      }
  1271. X      result = -1;
  1272. X      break;
  1273. X
  1274. X    case 1:
  1275. X      if ( iflag ) {
  1276. X        buf[0] = '\0';
  1277. X
  1278. X        emit(ofile,commandname);
  1279. X        emit(ofile,": remove ");
  1280. X        emit(ofile,file);
  1281. X        emit(ofile,"? ");
  1282. X
  1283. X        Read(ifile,buf,BUFSIZE);
  1284. X
  1285. X        if ( buf[0] != 'y' && buf[0] != 'Y' ) {
  1286. X          result = -1;
  1287. X          break;
  1288. X        }
  1289. X      }
  1290. X
  1291. X      SetProtection(file,0);
  1292. X
  1293. X      if ( !DeleteFile(file) ) {
  1294. X        if ( !fflag ) {
  1295. X          emit(ofile,commandname);
  1296. X          emit(ofile,": could not remove ");
  1297. X          emit(ofile,file);
  1298. X          emit(ofile,"\n");
  1299. X        }
  1300. X        result = -1;
  1301. X      } else {
  1302. X        result = 1;
  1303. X      }
  1304. X      break;
  1305. X
  1306. X    case 0:
  1307. X      if ( !fflag ) {
  1308. X        buf[0] = '\0';
  1309. X
  1310. X        emit(ofile,commandname);
  1311. X        emit(ofile,": overide delete protection for file ");
  1312. X        emit(ofile,file);
  1313. X        emit(ofile,"? ");
  1314. X
  1315. X        Read(ifile,buf,BUFSIZE);
  1316. X
  1317. X        if ( buf[0] == 'y' || buf[0] == 'Y' ) {
  1318. X
  1319. X          SetProtection(file,0);
  1320. X
  1321. X          if ( !DeleteFile(file) ) {
  1322. X            if ( !fflag ) {
  1323. X              emit(ofile,commandname);
  1324. X              emit(ofile,": could not remove ");
  1325. X              emit(ofile,file);
  1326. X              emit(ofile,"\n");
  1327. X            }
  1328. X            result = -1;
  1329. X          } else {
  1330. X            result = 1;
  1331. X          }
  1332. X        } else {
  1333. X          result = -1;
  1334. X        }
  1335. X      } else {
  1336. X
  1337. X        SetProtection(file,0);
  1338. X
  1339. X        if ( !DeleteFile(file) ) {
  1340. X          if ( !fflag ) {
  1341. X            emit(ofile,commandname);
  1342. X            emit(ofile,": could not remove ");
  1343. X            emit(ofile,file);
  1344. X            emit(ofile,"\n");
  1345. X          }
  1346. X          result = -1;
  1347. X        } else {
  1348. X          result = 1;
  1349. X        }
  1350. X      }
  1351. X      break;
  1352. X  }
  1353. X
  1354. X  freebuf(buf);
  1355. X  return(result);
  1356. X}
  1357. X
  1358. X
  1359. X/* recursively remove a directory or a remove a file */
  1360. Xint rm_dir(name,fflag,iflag)
  1361. Xchar *name;
  1362. Xint fflag, iflag;
  1363. X{
  1364. X   register struct FileLock *lock, *cwd;
  1365. X   register struct FileInfoBlock *fib;
  1366. X   register char *buf;
  1367. X   register int result = 1;
  1368. X
  1369. X# ifdef DEBUG
  1370. X  printf("Recursively deleting directory %s\n",name);
  1371. X# endif
  1372. X
  1373. X   buf = newbuf();
  1374. X   fib = (struct FileInfoBlock *)AllocMem(FIBSIZE,MEMF_CLEAR);
  1375. X
  1376. X   if (lock = Lock(name, ACCESS_READ)) {
  1377. X
  1378. X      cwd = CurrentDir(lock);
  1379. X
  1380. X      if (Examine(lock, fib)) {
  1381. X
  1382. X         buf[0] = '\0';
  1383. X
  1384. X         while (result && ExNext(lock, fib)) {
  1385. X
  1386. X            if ( fib->fib_DirEntryType > 0 )
  1387. X               result = rm_dir(fib->fib_FileName,fflag,iflag);
  1388. X
  1389. X            if (buf[0]) {
  1390. X               rm_file(buf,fflag,iflag);
  1391. X            }
  1392. X
  1393. X            strcpy(buf, fib->fib_FileName);
  1394. X         }
  1395. X
  1396. X         if ( buf[0] ) {
  1397. X            rm_file(buf,fflag,iflag);
  1398. X         }
  1399. X      }
  1400. X
  1401. X      UnLock(CurrentDir(cwd));
  1402. X
  1403. X   } else {
  1404. X     if ( !fflag ) {
  1405. X        emit(ofile,commandname);
  1406. X        emit(ofile,": could not get a lock on ");
  1407. X        emit(ofile,name);
  1408. X        emit(ofile,"\n");
  1409. X      }
  1410. X      result = -1;
  1411. X   }
  1412. X
  1413. X   FreeMem(fib, FIBSIZE);
  1414. X   freebuf(buf);
  1415. X
  1416. X   return(result);
  1417. X}
  1418. X
  1419. Xrm(name,fflag,iflag)
  1420. Xchar *name;
  1421. Xint fflag,iflag;
  1422. X{
  1423. X  int result;
  1424. X  struct FileInfoBlock *fib;
  1425. X
  1426. X  switch ( isdir(name,&fib) ) {
  1427. X    case 0:
  1428. X      result = rm_file(name,fflag,iflag);
  1429. X      break;
  1430. X
  1431. X    case 1:
  1432. X      if ( rflag ) {
  1433. X        /* recursively delete the directory */
  1434. X        result = rm_dir(name,fflag,iflag);
  1435. X        if ( result ) {
  1436. X          rm_file(name,fflag,iflag);
  1437. X        }
  1438. X      } else if ( dflag ) {
  1439. X
  1440. X        /* only deletes directory if it is empty, as in AmigaDOS Delete */
  1441. X        result = rm_file(name,fflag,iflag);
  1442. X
  1443. X      } else {
  1444. X        if ( !fflag ) {
  1445. X          emit(ofile,commandname);
  1446. X          emit(ofile,": ");
  1447. X          emit(ofile,name);
  1448. X          emit(ofile," is a directory (not removed)\n");
  1449. X        }
  1450. X        result = -1;
  1451. X      }
  1452. X      break;
  1453. X
  1454. X    case 2:
  1455. X      if ( !fflag ) {
  1456. X        emit(ofile,commandname);
  1457. X        emit(ofile,": could not access file ");
  1458. X        emit(ofile,name);
  1459. X        emit(ofile,"\n");
  1460. X      }
  1461. X      break;
  1462. X
  1463. X
  1464. X    case 3:
  1465. X      if ( !fflag ) {
  1466. X        emit(ofile,commandname);
  1467. X        emit(ofile,": could not examine file ");
  1468. X        emit(ofile,name);
  1469. X        emit(ofile,"\n");
  1470. X      }
  1471. X      break;
  1472. X  }
  1473. X
  1474. X  if ( fib )
  1475. X    freefib(fib);
  1476. X
  1477. X  return(result);
  1478. X}
  1479. X
  1480. X
  1481. X/* mv a file or directory _to_a_directory_ */
  1482. Xint mv(src,dst)
  1483. Xchar *src, *dst;
  1484. X{
  1485. X  register int result = 0;
  1486. X  struct FileInfoBlock *srcfib;
  1487. X
  1488. X  switch ( isdir(src,&srcfib) ) {
  1489. X
  1490. X    /* source is a file */
  1491. X    case 0:
  1492. X      result = mvfile(src,srcfib,dst);
  1493. X      break;
  1494. X
  1495. X    /* source is a directory */
  1496. X    case 1:
  1497. X      result = mvdir(src,srcfib,dst);
  1498. X      break;
  1499. X
  1500. X    /* no access to source */
  1501. X    case 2:
  1502. X      if ( !fflag ) {
  1503. X        emit(ofile,commandname);
  1504. X        emit(ofile,": could not access file ");
  1505. X        emit(ofile,src);
  1506. X        emit(ofile,"\n");
  1507. X      }
  1508. X      result = 0;
  1509. X      break;
  1510. X
  1511. X    /* not able to examine source */
  1512. X    case 3:
  1513. X      if ( !fflag ) {
  1514. X        emit(ofile,commandname);
  1515. X        emit(ofile,": could not examine file ");
  1516. X        emit(ofile,src);
  1517. X        emit(ofile,"\n");
  1518. X      }
  1519. X      result = 0;
  1520. X      break;
  1521. X  }
  1522. X
  1523. X  freefib(srcfib);
  1524. X  return(result);
  1525. X}
  1526. X
  1527. X/* mv to a destination dir _from_ a directory source */
  1528. Xint mvdir(src,srcfib,dst)
  1529. Xchar *src, *dst;
  1530. Xstruct FileInfoBlock *srcfib;
  1531. X{
  1532. X  register int result = 1, temp, onsame;
  1533. X  struct FileInfoBlock *dstfib;
  1534. X
  1535. X  if ( (onsame = samedev(src,dst)) == -1 )
  1536. X    return(0);
  1537. X
  1538. X  temp = isdir(dst,&dstfib);
  1539. X
  1540. X  /* if they are on the same device, treat the src dir as a file */
  1541. X  if ( onsame && mvflag ) {
  1542. X
  1543. X    /* if the destination dir doesn't exist, then move onto it... */
  1544. X    if ( temp == 2 ) {
  1545. X
  1546. X      result = mv2f(src,srcfib,dst,NULL);
  1547. X    } else {
  1548. X
  1549. X      /* ...else move into it */
  1550. X      result = mv2d(src,srcfib,dst);
  1551. X    }
  1552. X
  1553. X  } else if ( mvflag || (cpflag && rflag) ) {
  1554. X
  1555. X    /* ugh. We have to copy the source dir to the destination dir */
  1556. X
  1557. X    register int success, len;
  1558. X    register char c;
  1559. X    register struct FileLock *oldlock, *newlock, *dstlock;
  1560. X    char *buf = newbuf();
  1561. X    char *dstbuf = newbuf();
  1562. X    register struct FileInfoBlock *fib = newfib();
  1563. X
  1564. X    if ( !fib || !buf || !dstbuf ) {
  1565. X      result = -1;
  1566. X    } else {
  1567. X
  1568. X      dstbuf[0] = '\0';
  1569. X
  1570. X      strcat(dstbuf,dst);
  1571. X
  1572. X      if ( temp != 2 ) {
  1573. X        /*
  1574. X         * build the name of the destination from the directory name and
  1575. X         * later, the file name
  1576. X         */
  1577. X
  1578. X        len = strlen(dstbuf);
  1579. X
  1580. X        /*
  1581. X         * only append a slash if the file name is not the current directory,
  1582. X         * (ie. "") the last character is not null, and the last character
  1583. X         * is neither of ':' or '/'. This part is so much easier under Unix
  1584. X         * path naming conventions, but hey, Amigoids gotta be different!
  1585. X         */
  1586. X        if ( len && (c = dstbuf[len - 1] ) && c != ':' && c != '/' )
  1587. X          strcat(dstbuf,"/");
  1588. X
  1589. X        /*
  1590. X         * add only the file name onto the destination directory to
  1591. X         * build the name of the file we want to move to
  1592. X         */
  1593. X        strcat(dstbuf,basename(src));
  1594. X      }
  1595. X
  1596. X      /* see if the directory exists */
  1597. X      if ( !(dstlock = Lock(dstbuf,ACCESS_READ)) ) {
  1598. X        struct DateStamp ds;
  1599. X
  1600. X        /* if no lock, try creating it */
  1601. X
  1602. X        if ( iflag ) {
  1603. X          buf[0] = '\0';
  1604. X
  1605. X          emit(ofile,commandname);
  1606. X          emit(ofile,": create directory ");
  1607. X          emit(ofile,dstbuf);
  1608. X          emit(ofile,"? ");
  1609. X
  1610. X          Read(ifile,buf,BUFSIZE);
  1611. X
  1612. X          if ( buf[0] != 'y' && buf[0] != 'Y' ) {
  1613. X            freefib(fib);
  1614. X            freefib(dstfib);
  1615. X
  1616. X            return(0);
  1617. X          }
  1618. X        }
  1619. X
  1620. X        if ( !(dstlock = CreateDir(dstbuf)) ) {
  1621. X          if ( !fflag ) {
  1622. X            emit(ofile,commandname);
  1623. X            emit(ofile,": unable to create directory ");
  1624. X            emit(ofile,dstbuf);
  1625. X            emit(ofile,"\n");
  1626. X          }
  1627. X          return(0);
  1628. X        }
  1629. X#       ifdef DEBUG
  1630. X        printf("Created directory %s\n",dstbuf);
  1631. X#       endif
  1632. X
  1633. X        setdate(&srcfib->fib_Date,dstbuf);
  1634. X
  1635. X      }
  1636. X
  1637. X      UnLock(dstlock);
  1638. X
  1639. X      /*
  1640. X       * get a lock on the source directory, since we have to copy it
  1641. X       * recursively
  1642. X       */
  1643. X      newlock = Lock(src,ACCESS_READ);
  1644. X
  1645. X      /* Take a look at the directory */
  1646. X      success = Examine(newlock,fib);
  1647. X
  1648. X      /*
  1649. X       * while the examination of the source directory worked and the
  1650. X       * last move worked...
  1651. X       */
  1652. X      while ( ExNext(newlock,fib) && result > 0 ) {
  1653. X
  1654. X        /* build the source file name */
  1655. X        buf[0] = '\0';
  1656. X
  1657. X        strcat(buf,src);
  1658. X
  1659. X        len = strlen(buf);
  1660. X
  1661. X        if ( len && (c = buf[len - 1] ) && c != ':' && c != '/' )
  1662. X          strcat(buf,"/");
  1663. X
  1664. X        strcat(buf,&fib->fib_FileName[0]);
  1665. X
  1666. X        result = mv(buf,dstbuf);
  1667. X      }
  1668. X
  1669. X      UnLock(newlock);
  1670. X    }
  1671. X
  1672. X    freefib(fib);
  1673. X    freebuf(buf);
  1674. X    freebuf(dstbuf);
  1675. X
  1676. X  } else {
  1677. X    if ( !fflag ) {
  1678. X      emit(ofile,commandname);
  1679. X      emit(ofile,": ");
  1680. X      emit(ofile,src);
  1681. X      emit(ofile," is a directory (not copied)\n");
  1682. X    }
  1683. X  }
  1684. X
  1685. X  freefib(dstfib);
  1686. X
  1687. X  return(result);
  1688. X}
  1689. X
  1690. X/* mv to a destination file or directory _from_ a file */
  1691. Xint mvfile(src,srcfib,dst)
  1692. Xchar *src, *dst;
  1693. Xstruct FileInfoBlock *srcfib;
  1694. X{
  1695. X  register int result = 0;
  1696. X  struct FileInfoBlock *dstfib;
  1697. X  char *buf = newbuf();
  1698. X
  1699. X  if ( !buf ) {
  1700. X    return(-1);
  1701. X  }
  1702. X
  1703. X  switch ( isdir(dst,&dstfib) ) {
  1704. X
  1705. X    /* destination is a file */
  1706. X    case 0:
  1707. X      result = mv2f(src,srcfib,dst,dstfib);
  1708. X      break;
  1709. X
  1710. X    /* destination is a directory */
  1711. X    case 1:
  1712. X      result = mv2d(src,srcfib,dst);
  1713. X      break;
  1714. X
  1715. X    case 2:
  1716. X      if ( iflag ) {
  1717. X        buf[0] = '\0';
  1718. X
  1719. X        emit(ofile,commandname);
  1720. X        emit(ofile,": create directory ");
  1721. X        emit(ofile,dst);
  1722. X        emit(ofile,"? ");
  1723. X
  1724. X        Read(ifile,buf,BUFSIZE);
  1725. X
  1726. X        if ( buf[0] != 'y' && buf[0] != 'Y' ) {
  1727. X          result = 0;
  1728. X          break;
  1729. X        }
  1730. X      }
  1731. X#     ifdef DEBUG
  1732. X      printf("Creating dir %s\n",dst);
  1733. X#     endif
  1734. X
  1735. X      lock = CreateDir(dst);
  1736. X
  1737. X      if ( !lock ) {
  1738. X        if ( !fflag ) {
  1739. X          emit(ofile,commandname);
  1740. X          emit(ofile,": could not create destination directory ");
  1741. X          emit(ofile,dst);
  1742. X          emit(ofile,"\n");
  1743. X        }
  1744. X        result = 0;
  1745. X      } else {
  1746. X
  1747. X        UnLock(lock);
  1748. X        result = mv2d(src,srcfib,dst);
  1749. X      }
  1750. X
  1751. X      break;
  1752. X
  1753. X    case 3:
  1754. X      if ( !fflag ) {
  1755. X        emit(ofile,commandname);
  1756. X        emit(ofile,": could not examine directory ");
  1757. X        emit(ofile,dst);
  1758. X        emit(ofile,"\n");
  1759. X      }
  1760. X      result = 0;
  1761. X      break;
  1762. X  }
  1763. X
  1764. X  freefib(dstfib);
  1765. X  freebuf(buf);
  1766. X  return(result);
  1767. X}
  1768. X
  1769. X/* mv a file _to_ a directory dst */
  1770. Xint mv2d(src,srcfib,dst)
  1771. Xchar *src, *dst;
  1772. Xstruct FileInfoBlock *srcfib;
  1773. X{
  1774. X  char *buf = newbuf();
  1775. X  register char c;
  1776. X  register int result = 0;
  1777. X  register int len = strlen(dst);
  1778. X  struct FileInfoBlock *dstfib;
  1779. X
  1780. X  if ( !buf ) {
  1781. X    return(-1);
  1782. X  }
  1783. X
  1784. X  buf[0] = '\0';
  1785. X
  1786. X  /* build the file name in the destination directory */
  1787. X  strcat(buf,dst);
  1788. X
  1789. X  if ( len && (c = buf[len - 1] ) && c != ':' && c != '/' )
  1790. X    strcat(buf,"/");
  1791. X
  1792. X  strcat(buf,basename(src));
  1793. X
  1794. X  switch ( isdir(buf,&dstfib) ) {
  1795. X
  1796. X    case 0:
  1797. X      result = mv2f(src,srcfib,buf,dstfib);
  1798. X      break;
  1799. X
  1800. X    case 1:
  1801. X      if ( !fflag ) {
  1802. X        emit(ofile,commandname);
  1803. X        emit(ofile,": could not move file ");
  1804. X        emit(ofile,src);
  1805. X        emit(ofile," onto directory ");
  1806. X        emit(ofile,buf);
  1807. X        emit(ofile,"\n");
  1808. X      }
  1809. X      result = 0;
  1810. X      break;
  1811. X
  1812. X    case 2:
  1813. X      result = mv2f(src,srcfib,buf,NULL);
  1814. X      break;
  1815. X
  1816. X    case 3:
  1817. X      if ( !fflag ) {
  1818. X        emit(ofile,commandname);
  1819. X        emit(ofile,": something is awry with file ");
  1820. X        emit(ofile,buf);
  1821. X        emit(ofile,"\n");
  1822. X      }
  1823. X      result = 0;
  1824. X      break;
  1825. X  }
  1826. X
  1827. X  freefib(dstfib);
  1828. X  freebuf(buf);
  1829. X  return(result);
  1830. X}
  1831. X
  1832. X/* mv a file _to_ a file */
  1833. Xint mv2f(src,srcfib,dst,dstfib)
  1834. Xchar *src, *dst;
  1835. Xstruct FileInfoBlock *srcfib, *dstfib;
  1836. X{
  1837. X  register int result = 0, cleanup = 0;
  1838. X  char *inputbuf;
  1839. X  register int onsame;
  1840. X
  1841. X  /* are they on the same volume? */
  1842. X  if ( (onsame = samedev(src,dst)) == -1) {
  1843. X    freebuf(inputbuf);
  1844. X    return(0);
  1845. X  }
  1846. X
  1847. X  if ( !(inputbuf = newbuf()) ) {
  1848. X    return(-1);
  1849. X  }
  1850. X
  1851. X  if ( dstfib ) {
  1852. X    if ( onsame && srcfib->fib_DiskKey == dstfib->fib_DiskKey ) {
  1853. X
  1854. X      if ( !mvflag ) {
  1855. X        if ( !fflag ) {
  1856. X          emit(ofile,commandname);
  1857. X          emit(ofile,": cannot copy ");
  1858. X          emit(ofile,src);
  1859. X          emit(ofile," to itself!\n");
  1860. X        }
  1861. X        freebuf(inputbuf);
  1862. X        return(1);
  1863. X      }
  1864. X
  1865. X    } else {
  1866. X
  1867. X      if ( iflag ) {
  1868. X        inputbuf[0] = '\0';
  1869. X
  1870. X        emit(ofile,commandname);
  1871. X        emit(ofile,": overwrite ");
  1872. X        emit(ofile,dst);
  1873. X        emit(ofile,"? ");
  1874. X
  1875. X        Read(ifile,inputbuf,BUFSIZE);
  1876. X
  1877. X        if ( inputbuf[0] != 'y' && inputbuf[0] != 'Y' ) {
  1878. X          freebuf(inputbuf);
  1879. X          return(1);
  1880. X        }
  1881. X
  1882. X        /* if remove unsuccessful, return an error */
  1883. X        if ( rm_file(dst,1,0) == -1 ) {
  1884. X          freebuf(inputbuf);
  1885. X          return(0);
  1886. X        }
  1887. X
  1888. X      } else {
  1889. X
  1890. X        /* if remove unsuccessful, return an error */
  1891. X        if ( rm_file(dst,fflag,0) == -1 ) {
  1892. X          freebuf(inputbuf);
  1893. X          return(0);
  1894. X        }
  1895. X
  1896. X      }
  1897. X    }
  1898. X  }
  1899. X
  1900. X  result = (onsame && mvflag) ? move(src,dst) : cp(src,srcfib,dst);
  1901. X
  1902. X  freebuf(inputbuf);
  1903. X
  1904. X  return(result);
  1905. X}
  1906. X
  1907. X/* copy a source file to a destination file */
  1908. Xint cp(src,srcfib,dst)
  1909. Xchar *src, *dst;
  1910. Xstruct FileInfoBlock *srcfib;
  1911. X{
  1912. X  register int num;
  1913. X  register long size;
  1914. X  register char *buf;
  1915. X  struct FileHandle *srchandle, *dsthandle;
  1916. X
  1917. X# ifdef DEBUG
  1918. X  printf("copy file %s to %s\n",src,dst);
  1919. X# endif
  1920. X
  1921. X  size = mem() - 4;
  1922. X
  1923. X  if ( size < 128 ) {
  1924. X    if ( !fflag ) {
  1925. X      emit(ofile,commandname);
  1926. X      emit(ofile,": Out of memory!\n");
  1927. X    }
  1928. X    return(-1);
  1929. X  }
  1930. X
  1931. X  /*
  1932. X   * allocate a maximum of "size" continous bytes, else source file
  1933. X   * size worth of bytes. This allows one read and one write if there
  1934. X   * is enough memory for it. The 8 is added in case there is a
  1935. X   * zero size file we want to copy and we still want to allocate
  1936. X   * a buffer anyways.
  1937. X   */
  1938. X  size = ( srcfib->fib_Size + 8 > size ) ? size : srcfib->fib_Size + 8;
  1939. X
  1940. X# ifdef DEBUG
  1941. X  printf("Allocating %d bytes for the copy\n",size);
  1942. X# endif
  1943. X
  1944. X  if ( !(buf = AllocMem(size,MEMF_CLEAR|MEMF_PUBLIC)) ) {
  1945. X    /* didn't work, try again with a smaller size */
  1946. X    size = size / 4;
  1947. X
  1948. X    if ( !(buf = AllocMem(size,MEMF_CLEAR|MEMF_PUBLIC)) ) {
  1949. X      if ( !fflag ) {
  1950. X        emit(ofile,commandname);
  1951. X        emit(ofile,": Out of memory!\n");
  1952. X      }
  1953. X      return(-1);
  1954. X    }
  1955. X  }
  1956. X
  1957. X  /* if we can't open the file, return an error */
  1958. X  if ( !(dsthandle = Open(dst,MODE_NEWFILE)) ) {
  1959. X    if ( !fflag ) {
  1960. X      emit(ofile,commandname);
  1961. X      emit(ofile,": cannot Open file ");
  1962. X      emit(ofile,dst);
  1963. X      emit(ofile,"\n");
  1964. X    }
  1965. X    FreeMem(buf,size);
  1966. X
  1967. X    /* returning 0 indicates an error to the above routines */
  1968. X    return(0);
  1969. X  }
  1970. X
  1971. X  if ( !(srchandle = Open(src,MODE_OLDFILE)) ) {
  1972. X    if ( !fflag ) {
  1973. X      emit(ofile,commandname);
  1974. X      emit(ofile,": cannot Open file ");
  1975. X      emit(ofile,src);
  1976. X      emit(ofile,"\n");
  1977. X    }
  1978. X    Close(dsthandle);
  1979. X    FreeMem(buf,size);
  1980. X    return(0);
  1981. X  }
  1982. X
  1983. X  /* copy bytes back and forth. Read returns -1 for a read error */
  1984. X  while ( (num = Read(srchandle,buf,size)) > 0 ) {
  1985. X    if ( Write(dsthandle,buf,num) == -1 ) {
  1986. X      if ( !fflag ) {
  1987. X        emit(ofile,commandname);
  1988. X        emit(ofile,": error writing to file ");
  1989. X        emit(ofile,dst);
  1990. X        emit(ofile,". Disk may be full.\n");
  1991. X      }
  1992. X      Close(srchandle);
  1993. X      Close(dsthandle);
  1994. X      FreeMem(buf,size);
  1995. X      return(-1);
  1996. X    }
  1997. X  }
  1998. X
  1999. X  Close(srchandle);
  2000. X  Close(dsthandle);
  2001. X
  2002. X  if ( num == -1 ) {
  2003. X    if ( !fflag ) {
  2004. X      emit(ofile,commandname);
  2005. X      emit(ofile,": error reading from file ");
  2006. X      emit(ofile,src);
  2007. X      emit(ofile,"\n");
  2008. X    }
  2009. X    FreeMem(buf,size);
  2010. X    return(0);
  2011. X  }
  2012. X
  2013. X  if ( nflag ) {
  2014. X    /*
  2015. X     * copy the protection bits, the comment and the datestamp to the
  2016. X     * new file if the n flag is set (ie. -n was NOT specified in the
  2017. X     * commandline)
  2018. X     */
  2019. X    SetProtection(dst,srcfib->fib_Protection);
  2020. X
  2021. X    SetComment(dst,srcfib->fib_Comment);
  2022. X
  2023. X    setdate(&srcfib->fib_Date,dst);
  2024. X
  2025. X    FreeMem(buf,size);
  2026. X  }
  2027. X
  2028. X  /* return 2 for successful copy (not 1, because 1 is a move) */
  2029. X  return(2);
  2030. X}
  2031. X
  2032. X/* rename a source file to a destination file */
  2033. Xint move(src,dst)
  2034. Xchar *src, *dst;
  2035. X{
  2036. X  register int foo;
  2037. X
  2038. X# ifdef DEBUG
  2039. X  printf("move file %s to %s\n",src,dst);
  2040. X# endif
  2041. X
  2042. X  /* return 1 for successful move */
  2043. X  foo =  Rename(src,dst) ? 1 : 0;
  2044. X
  2045. X  if ( !foo && !fflag ) {
  2046. X    emit(ofile,commandname);
  2047. X    emit(ofile,": could not move file ");
  2048. X    emit(ofile,src);
  2049. X    emit(ofile," to ");
  2050. X    emit(ofile,dst);
  2051. X    emit(ofile,"\n");
  2052. X  }
  2053. X
  2054. X  return(foo);
  2055. X}
  2056. X
  2057. Xint setdate(date,name)
  2058. Xstruct DateStamp *date;
  2059. Xchar *name;
  2060. X{
  2061. X  register UBYTE *ptr;
  2062. X  struct MsgPort *task;
  2063. X  register struct FileLock *lock, *parent;
  2064. X  register struct FileInfoBlock *fib;
  2065. X  int stat, result, dos_packet();
  2066. X
  2067. X  if ( !(task = DeviceProc(name)) ) {
  2068. X    return(0);
  2069. X  }
  2070. X
  2071. X  if ( !(lock = Lock(name,ACCESS_READ)) ) {
  2072. X    return(0);
  2073. X  }
  2074. X
  2075. X  fib = newfib();
  2076. X
  2077. X  /*
  2078. X   * thanks to Matt Dillon for this routine. I really don't know how
  2079. X   * it does what it does, but it works, so no comments here.
  2080. X   */
  2081. X
  2082. X  /*
  2083. X   * Well, I mean other than these comments...
  2084. X   */
  2085. X
  2086. X  /*
  2087. X   * Oh, forget it.
  2088. X   */
  2089. X  if ( fib ) {
  2090. X    if ( Examine(lock,fib) ) {
  2091. X
  2092. X      parent = ParentDir(lock);
  2093. X
  2094. X      UnLock(lock);
  2095. X
  2096. X      ptr = (UBYTE *) AllocMem(256L,MEMF_CLEAR|MEMF_PUBLIC);
  2097. X
  2098. X      strcpy((ptr + 1),fib->fib_FileName);
  2099. X
  2100. X      *ptr = (UBYTE) strlen(fib->fib_FileName);
  2101. X
  2102. X      result = dos_packet(task,34L,NULL,parent,(ULONG)&ptr[0] >> 2L,date);
  2103. X
  2104. X      FreeMem(ptr,256L);
  2105. X
  2106. X      UnLock(parent);
  2107. X    }
  2108. X
  2109. X    freefib(fib);
  2110. X
  2111. X  } else {
  2112. X    UnLock(lock);
  2113. X  }
  2114. X}
  2115. X
  2116. X/* is a file delete protected? */
  2117. Xint isdeletable(file)
  2118. Xchar *file;
  2119. X{
  2120. X  register struct FileLock *lock;
  2121. X  register struct FileInfoBlock *fib;
  2122. X  register int result = 0;
  2123. X
  2124. X  if ( !(lock = Lock(file,ACCESS_READ)) ) {
  2125. X    return(0);
  2126. X  }
  2127. X
  2128. X  /* allocate a word aligned memory block to hold our info */
  2129. X  fib = newfib();
  2130. X
  2131. X  if ( fib ) {
  2132. X    if ( Examine(lock,fib) ) {
  2133. X
  2134. X      result = fib->fib_Protection;
  2135. X      freefib(fib);
  2136. X
  2137. X    } else {
  2138. X
  2139. X      freefib(fib);
  2140. X      return(2);
  2141. X    }
  2142. X
  2143. X  }
  2144. X
  2145. X
  2146. X  UnLock(lock);
  2147. X
  2148. X  return( !(result & FIBF_DELETE) );
  2149. X}
  2150. X
  2151. X
  2152. SHAR_EOF
  2153. echo "extracting mv.uu"
  2154. sed 's/^X//' << \SHAR_EOF > mv.uu
  2155. X
  2156. Xbegin 644 mv
  2157. XM```#\P`````````#``````````(```U@````,0````$```/I```-8$[Z+I).)
  2158. XM5?_\(&R`;B`L@&Z0J``$4(`I0(!R(&R`<B"\34%.6$*G3KHTPEA/*T#__"\M)
  2159. XM``PO+0`(+RW__$ZZ+M!/[P`,*7P````!@'8O+(!Z+RR`?DZZ"-Q03R\`3KHQ4
  2160. XMJEA/3EU.=4Y5``!(YP@P)&T`""9M``PO"DZZ+/Y83]"**`!3A"!*4XBQQ&<:G
  2161. XM($00$$B`2,`O`"\+3KHM(%!/2H!F!%.$8-X@2E.(L<1G!"`$8`)P`$S?#!!.J
  2162. XM74YU3E4``$CG"#`D;0`()FT`#'@`2C)(`&<R2C-(`&<L$#)(`$B`2,`O`$ZZ@
  2163. XM++Q83R\`$#-(`$B`2,`O`$ZZ+*I83R(?LH!F!%*$8,@0,D@`2(!(P"\`3KHLE
  2164. XMD%A/+P`0,T@`2(!(P"\`3KHL?EA/(A^R@&P$</]@+A`R2`!(@$C`+P!.NBQD*
  2165. XM6$\O`!`S2`!(@$C`+P!.NBQ26$\B'[*`;P1P`6`"<`!,WPP03EU.=4Y5``!(6
  2166. XMYP`P)&T`"$AZ`"`O"DZZ_NI03R9`(`MG!B`+4H!@`B`*3-\,`$Y=3G4Z+P``O
  2167. XM3E4``"\M``Q.NBO46$\O`"\M``PO+0`(3KHR]D_O``Q.74YU3E7_^$ZZ,S9(O
  2168. XM>``"3KHR\%A/*T#__$AX``1.NC+B6$\K0/_X3KHS6B`M__RPK?_X;P8@+?_\(
  2169. XM8`0@+?_X3EU.=4Y5__Q(>0`!``!(>`$$3KHRRE!/*T#__$JM__QF*$JL@!)FR
  2170. XM'$AL@"(O+(!:3KK_;E!/2'H`&"\L@%I.NO]@4$]P`$Y=3G4@+?_\8/8Z($]UJ
  2171. XM="!O9B!M96UO<GDA"@!.50``2JT`"&<.2'@!!"\M``A.NC*64$].74YU3E4`-
  2172. XM`"\*2'D``0`!2'@!`$ZZ,DY03R1`(`IF*DJL@!)F'$AL@"(O+(!:3KK^]E!/R
  2173. XM2'H`&"\L@%I.NO[H4$]P`"1?3EU.=2`*8/8Z($]U="!O9B!M96UO<GDA"@!.V
  2174. XM50``2JT`"&<.2'@!`"\M``A.NC(>4$].74YU3E7__$AY``$``4AX`01.NC'8*
  2175. XM4$\K0/_\2JW__&<.(&W__$(0(&W__$*H`0`@+?_\3EU.=4Y5``!*K0`(9QH@R
  2176. XM;0`(+R@!`&'L6$](>`$$+RT`"$ZZ,<)03TY=3G5.50``2JT`"&<@(&T`"$JHB
  2177. XM`0!G$"!M``@O*`$`8>)83TY=3G4@+0`(8/9P`&#R3E4``"!M``A*J`$`9Q(@N
  2178. XM;0`(+R@!`&'H6$]2@$Y=3G5P`6#X3E4``"\$>``@;0`(2C!(`&<H(&T`"`PP+
  2179. XM`"I(`&<<(&T`"`PP`#](`&<0(&T`"`PP`"-(`&<$4H1@SB!M``@0,$@`2(!(<
  2180. XMP"@?3EU.=4Y5__!*K(!"9P``_B\M``AAHEA/2H!G``#P(&T`#$*02'D``0`!!
  2181. XM2'@"&DZZ,,)03RM`__`@;?_P(7P```$``!`O+?_P+RT`"$ZZ)LQ03TJ`9Q`OQ
  2182. XM+?_P3KHFV%A/<`!.74YU3KK^HBM`__QG%"!M__!(:`$8+RW__$ZZ+(!03V`87
  2183. XM(&T`#""\`````2\M__!.NB:@6$]P`&#&*VW__/_X+RW_\$ZZ)H!83RM`__1FZ
  2184. XM3DZZ_E8@;?_X(4`!`&8B(&T`#""\`````2\M__!.NB9D6$\O+?_\3KK^9%A/Z
  2185. XM<`!@@"!M__@K:`$`__@@;?_P2&@!&"\M__A.NBP$4$]@HB\M__!.NB8N6$]@^
  2186. XM-$ZZ_?PK0/_\2JW__&<6(&T`#$*0+RT`""\M__Q.NBO44$]@$"!M``P@O```[
  2187. XM``%P`&``_R0@+?_\8`#_'$Y5``!*K(!29PHO+(!23KHO7%A/2'C__TZZ+,!8$
  2188. XM3TY=3G5.5?_\+PI(>0`!```O+0`(3KHH%EA/4H`O`$ZZ+VQ03RM`__PO+0`(T
  2189. XM+RW__$ZZ*V903R\M__Q.NOO@6$\D0$(2("W__"1?3EU.=4Y5_ZA(>/_^+RT`$
  2190. XM"$ZZ+H)03^6`*T#_J$JM_ZAF!G#_3EU.=2!M_Z@@*``0Y8`@0"`H`"CE@"M`.
  2191. XM_ZP@;?^L$!!(@$C`4H`O`"!M_ZQ2B"\(2&W_V$ZZ*QY/[P`,(&W_K!`02(!(L
  2192. XMP$'M_]I",`@`("W_J.2`+P!.NBZ(6$\O+0`,3KK_-%A/*T#_K$AX__XO+?^L1
  2193. XM3KHM_%!/Y8`K0/^H+RT`#$ZZ)SI83U*`+P`O+?^L3KHNNE!/2JW_J&8&</]@O
  2194. XM`/]@(&W_J"`H`!#E@"!`("@`*.6`*T#_K"!M_ZP0$$B`2,!2@"\`(&W_K%*(6
  2195. XM+PA(;?^P3KHJ@$_O``P@;?^L$!!(@$C`0>W_LD(P"``@+?^HY(`O`$ZZ+>I86
  2196. XM3TAM_[!(;?_83KKY_E!/2H!F!'`!8`)P`$C`8`#^ZDY5__PO!$ZZ^R0@;0`,U
  2197. XM((!(>/_^+RT`"$ZZ+3Y03RM`__QF"'`"*!].74YU(&T`#$J09RX@;0`,+Q`O=
  2198. XM+?_\3KHL[%!/2H!G%B!M``PB4$JI``1O!'`!8`)P`"@`8`)X`V`P2JR`$F8<%
  2199. XM2&R`(B\L@%I.NOI64$](>@`H+RR`6DZZ^DA03R\M__Q.NBT^6$]P_V"4+RW_Y
  2200. XM_$ZZ+3!83R`$8(8Z($]U="!O9B!M96UO<GDA"@!.50``2JR`8F<*+RR`8DZZN
  2201. XM+3183TJL@&9G"B\L@&9.NBTD6$]*K(!J9PHO+(!J3KHM%%A/3EU.=4Y5``!*W
  2202. XMK(`29E1(>@!D+RR`6DZZ^<I03TAZ`'PO+(!:3KKYO%!/2'H`GB\L@%I.NOFN0
  2203. XM4$](>@"V+RR`6DZZ^:!03TAZ`-@O+(!:3KKYDE!/2'H`]2\L@%I.NOF$4$].K
  2204. XMNO]H2'@``4ZZ*>183TY=3G55<V%G93H@;78@6RUC9FEX72`@("!;+5T@9FELM
  2205. XM93$@9FEL93(*`"`@("`@("!M=B!;+6-F:7A=("`@(%LM72!P871H,2!;<&%TG
  2206. XM:#(@+BXN72!D:7(*`"`@("`@("!C<"!;+69I;6YX72`@(%LM72!F:6QE,2!F@
  2207. XM:6QE,@H`("`@("`@(&-P(%LM9FEM;GAR4ET@6RU=('!A=&@Q(%MP871H,B`N_
  2208. XM+BY=(&1I<@H`("`@("`@(')M(%LM8V1F:6UR4ET@6RU=('!A=&@@(%MP871H'
  2209. XM("XN+ET*``I7:&5R92!P871H(&ES(&5I=&AE<B!A(&9I;&4@;W(@82!D:7)E'
  2210. XM8W1O<GDN"@``3E7_V$CG#`!"K?_\0JW_^$*M__1"K?_P0JW_[$AX`^Y(>@?VX
  2211. XM3KHJY%!/*4"`6DZZ*KPI0(!>0J=(>@?@3KHKNE!/*4"`8DJL@&)G9D*G2'H'M
  2212. XMUDZZ*Z103RE`@&9F'$AZ!]@O+(!:3KKX`%!/3KK]Y$AX__].NBA@6$]"ITAZ;
  2213. XM!]Q.NBMV4$\I0(!J9AQ(>@?=+RR`6DZZ]])03TZZ_;9(>/__3KHH,EA/*7P`R
  2214. XM```!@$)@!$*L@$)(>@?4(&T`#"\03KKW=%A/+P!.NO;`4$]*@&8*4JR``E*LJ
  2215. XM@`Y@)DAZ![$@;0`,+Q!.NO=.6$\O`$ZZ]II03TJ`9@92K(`*8`12K(`&>`$@_
  2216. XM!.6`(&T`#")P"``,$0`M9@`!9GH!(`3E@"!M``PB,`@`($5*,!@`9@92A&``#
  2217. XM`4H@!.6`(&T`#"(P"``@14HP&`!G``$N(`3E@"!M``PB,`@`($40,!@`2(!(=
  2218. XMP&```-`I?`````&`!D*L@`I"K(`"0JR`#F```/8I?`````&`'F```.HI?```)
  2219. XM``&`$D*L@!9@``#:0JR`$BE\`````8`68```RBE\`````8`"*7P````!@`Y"5
  2220. XMK(`*0JR`!F```*Y"K(`:8```IBE\`````8`.8```FBE\`````8`*0JR`!D*L&
  2221. XM@`)"K(`.8```@DAZ!J`O+(!:3KKV;E!/2'@``2`$Y8`@;0`,(G`(`-/%+PDO$
  2222. XM+(!:3KHI8$_O``Q(>@:"+RR`6DZZ]D!03TZZ_%Q@/I"\````4F>2D+P````1O
  2223. XM9P#_(E.`9P#_-%6`9P#_.E>`9P#_1%F`9P#_3E.`9P#_9%F`9P#_9EV`9P#_]
  2224. XM;&"`4H5@`/[`4H1@`/Z*("T`")"$+P!*K(`*9P1P`6`"<`(B'[*`;`1.NOOR?
  2225. XM2JR``F<02'H&`DAL@").NB4(4$]@)$JL@`IG$$AZ!>](;(`B3KHD\E!/8`Y(=
  2226. XM>@7B2&R`(DZZ).)03TAM_^`@!%*$Y8`@;0`,+S`(`$ZZ]]!03RM`__1*K?_@Y
  2227. XM9S!*K(`29AQ(;(`B+RR`6DZZ]6)03TAZ!:$O+(!:3KKU5%!/3KK[.$AX__].^
  2228. XMNB6T6$\O+?_T3KKV[EA/*T#_\&```)A*K?_P9R!(;?_@(`3E@"!M``PO,`@`X
  2229. XM3KKW:%!/(&W_\"%``0!@($AM_^`@!.6`(&T`#"\P"`!.NO=(4$\K0/_P*VW_8
  2230. XM\/_T2JW_X&<Z2JR`$F8<2&R`(B\L@%I.NO344$](>@4E+RR`6DZZ],903TZZH
  2231. XM^JHO+?_T3KKV0EA/2'C__TZZ)1Q83R\M__!.NO966$\K0/_P4H2XK0`(;0#_7
  2232. XM9"\M__1.NO8^6$\K0/_L+RW_]$ZZ]EY83RM`_^A*K(`*9@`#5$AM__@O+?_L`
  2233. XM3KKYG%!/8``#,`RM`````O_H9@``PDAM__PO+?_T3KKY?E!/2H!G1DJL@!)F;
  2234. XM'$AL@"(O+(!:3KKT+E!/2'H$D2\L@%I.NO0@4$\O+?_\3KKTV%A/+RW_^$ZZD
  2235. XM],Y83R\M__1.NO6,6$].NOH>8&8O+?_X+RW_["\M__PO+?_T3KH48$_O`!`K#
  2236. XM0/_D#*T````"_^1F&DJL@`)G%"\L@!8O+(`2+RW_]$ZZ"4!/[P`,+RW__$ZZ;
  2237. XM]'183R\M__A.NO1J6$\O+?_T3KKU*%A/0J=.NB0$6$]@.DJL@!)F'$AL@"(OS
  2238. XM+(!:3KKS@%!/2'H$"B\L@%I.NO-R4$\O+?_X3KKT*EA/+RW_]$ZZ].A83TZZS
  2239. XM^7I@``(X+RW_^$ZZ]`Y83V```BH,K0````+_Z&9Z2&W__"\M__1.NOAH4$]*O
  2240. XM@&9H0J<O+?_L+RW__"\M__1.NA.23^\`$"M`_^0,K0````+_Y&8:2JR``F<4^
  2241. XM+RR`%B\L@!(O+?_T3KH(<D_O``PO+?_X3KKSIEA/+RW__$ZZ\YQ83R\M__1.&
  2242. XMNO1:6$]"ITZZ(S983V```2P,K0````+_Z&\``2!.NO.0*T#_V"\M__Q.NO-HF
  2243. XM6$\O+?_X3KKS7EA/2JW_V&84+RW_]$ZZ]!983TAX__].NB+P6$]*K(`69UP@X
  2244. XM;?_80A!(;(`B+RR`6DZZ\FA03TAZ`QDO+(!:3KKR6E!/+RW_["\L@%I.NO),J
  2245. XM4$](>`$`+RW_V"\L@%Y.NB3Z3^\`#"!M_]@,$`!Y9PX@;?_8#!``66<$8``!/
  2246. XM`B\M_^Q.NB1"6$\K0/_<9F)*K(`29CA(;(`B+RR`6DZZ\?Q03TAZ`L$O+(!:K
  2247. XM3KKQ[E!/+RW_["\L@%I.NO'@4$](>@+#+RR`6DZZ\=)03TZZ][8O+?_T3KKS?
  2248. XM3EA/+RW_V$ZZ\O183TAX__].NB(>6$]@"B\M_]Q.NB2D6$\O+?_83KKRU%A/J
  2249. XM8'A*K(`29CA(;(`B+RR`6DZZ\8103TAZ`FDO+(!:3KKQ=E!/+RW_["\L@%I.?
  2250. XMNO%H4$](>@)G+RR`6DZZ\5I03R\M__1.NO+:6$\O+?_X3KKR"%A/2'@``TZZ5
  2251. XM(:I83V`:_,+]S/W:_XJPO`````1D"N.`,#L`[$[[```K;?_T__!@``">3KHA5
  2252. XM3B!M__"Q[?_L9VI*K(`"9@9*K(`&9UXO+?_L+RW_\$ZZ"%)03RM`_^0@+?_D:
  2253. XM8#9.NO;(+RW_]$ZZ\F!83TAX__].NB$Z6$]*K(`&9A0O+(`6+RR`$B\M__!.A
  2254. XMN@8V3^\`#&`08`Z0O/____]GPE>`9]9@\&`:2JR`"F<4+RR`%B\L@!(O+?_P1
  2255. XM3KH&"$_O``P@;?_P*V@!`/_P2JW_\&8`_UY.NO96+RW_]$ZZ\>Y83T*G3KH@*
  2256. XMREA/3-\`,$Y=3G4J`&%R<"YL:6)R87)Y`&EN='5I=&EO;BYL:6)R87)Y`$-O"
  2257. XM=6QD(&YO="!O<&5N(&EN='5I=&EO;BYL:6)R87)Y"@!G<F%P:&EC<RYL:6)R@
  2258. XM87)Y`$-O=6QD(&YO="!O<&5N(&=R87!H:6-S+FQI8G)A<GD*`&UV`')M`&EN]
  2259. XM=F%L:60@;W!T:6]N(``*`&UV`')M`&-P`#H@3W5T(&]F(&UE;6]R>2$*`#H@-
  2260. XM3W5T(&]F(&UE;6]R>2$*`#H@8V%N;F]T(&UO=F4@82!D:7)E8W1O<GD@;VYTL
  2261. XM;R!A(&9I;&4*`#H@8V%N;F]T(&UO=F4@82!D:7)E8W1O<GD@;VYT;R!A(&9IT
  2262. XM;&4*`#H@8W)E871E(&1I<F5C=&]R>2``.B!U;F%B;&4@=&\@8W)E871E(&1I3
  2263. XM<F5C=&]R>2``"@`Z(&-O=6QD(&YO="!E>&%M:6YE(&9I;&4@``H``$Y5__PO2
  2264. XM!$ZZ[\XK0/_\2JW__&8(</\H'TY=3G4O+0`(3KH6/%A/8``"3$JM``QF.$AL;
  2265. XM@"(O+(!:3KKNOE!/2'H"5B\L@%I.NNZP4$\O+0`(+RR`6DZZ[J)03TAZ`E$O2
  2266. XM+(!:3KKNE%!/>/]@``(:2JT`$&=L(&W__$(02&R`(B\L@%I.NNYT4$](>@(E3
  2267. XM+RR`6DZZ[F903R\M``@O+(!:3KKN6%!/2'H"$R\L@%I.NNY*4$](>`$`+RW_]
  2268. XM_"\L@%Y.NB#X3^\`#"!M__P,$`!Y9Q`@;?_\#!``66<&>/]@``&H0J<O+0`(J
  2269. XM3KHA`E!/+RT`"$ZZ($Y83TJ`9D)*K0`,9CA(;(`B+RR`6DZZ[>Y03TAZ`:PO)
  2270. XM+(!:3KKMX%!/+RT`""\L@%I.NNW24$](>@&D+RR`6DZZ[<103WC_8`)X`6``?
  2271. XM`49*K0`,9@``S"!M__Q"$$AL@"(O+(!:3KKMGE!/2'H!<B\L@%I.NNV04$\O0
  2272. XM+0`(+RR`6DZZ[8)03TAZ`7PO+(!:3KKM=%!/2'@!`"\M__PO+(!>3KH@(D_O5
  2273. XM``P@;?_\#!``>6<*(&W__`P0`%EF8$*G+RT`"$ZZ(#)03R\M``A.NA]^6$]*=
  2274. XM@&9"2JT`#&8X2&R`(B\L@%I.NNT>4$](>@$;+RR`6DZZ[1!03R\M``@O+(!:6
  2275. XM3KKM`E!/2'H!$R\L@%I.NNST4$]X_V`">`%@`GC_8%Y"IR\M``A.NA_.4$\OA
  2276. XM+0`(3KH?&EA/2H!F0DJM``QF.$AL@"(O+(!:3KKLNE!/2'H`S2\L@%I.NNRLL
  2277. XM4$\O+0`(+RR`6DZZ[)Y03TAZ`,4O+(!:3KKLD%!/>/]@`G@!8!)*@&<`_LI38
  2278. XM@&<`_?!3@&<`_:8O+?_\3KKMIEA/(`1@`/V".B!C;W5L9"!N;W0@9FEN9"!FV
  2279. XM:6QE(``*`#H@<F5M;W9E(``_(``Z(&-O=6QD(&YO="!R96UO=F4@``H`.B!O.
  2280. XM=F5R:61E(&1E;&5T92!P<F]T96-T:6]N(&9O<B!F:6QE(``_(``Z(&-O=6QD0
  2281. XM(&YO="!R96UO=F4@``H`.B!C;W5L9"!N;W0@<F5M;W9E(``*``!.50``2.<.C
  2282. XM,'P!3KKLHBH`2'D``0``2'@!!$ZZ'O)03R@`2'C__B\M``A.NAXT4$\D0$J`;
  2283. XM9P``H"\*3KH=S%A/)D`O!"\*3KH=[%!/2H!G="!%0A!*AF=4+P0O"DZZ'>A0*
  2284. XM3TJ`9T8@1$JH``1O%B\M`!`O+0`,($10B"\(88)/[P`,+``@14H09Q(O+0`0I
  2285. XM+RT`#"\%3KK\0D_O``P@1%"(+P@O!4ZZ%OA03V"H($5*$&<2+RT`$"\M``PO+
  2286. XM!4ZZ_!I/[P`,+PM.NAU`6$\O`$ZZ'@!83V!`2JT`#&8X2&R`(B\L@%I.NNKJ7
  2287. XM4$](>@!(+RR`6DZZZMQ03R\M``@O+(!:3KKJSE!/2'H`1R\L@%I.NNK`4$]\.
  2288. XM_TAX`00O!$ZZ'AY03R\%3KKKY%A/(`9,WPQP3EU.=3H@8V]U;&0@;F]T(&=E5
  2289. XM="!A(&QO8VL@;VX@``H``$Y5__A(;?_X+RT`"$ZZ[ZA03V```4HO+0`0+RT``
  2290. XM#"\M``A.NOMB3^\`#"M`__Q@``%`2JR`#F<T+RT`$"\M``PO+0`(3KK^:$_OI
  2291. XM``PK0/_\2JW__&<4+RT`$"\M``PO+0`(3KK[(D_O``Q@9DJL@!YG&B\M`!`O\
  2292. XM+0`,+RT`"$ZZ^P9/[P`,*T#__&!&2JT`#&8X2&R`(B\L@%I.NNGB4$](>@#F"
  2293. XM+RR`6DZZZ=103R\M``@O+(!:3KKIQE!/2'H`S2\L@%I.NNFX4$\K?/______V
  2294. XM_&```)Q*K0`,9CA(;(`B+RR`6DZZZ9A03TAZ`+XO+(!:3KKIBE!/+RT`""\L:
  2295. XM@%I.NNE\4$](>@"[+RR`6DZZZ6Y03V!:2JT`#&8X2&R`(B\L@%I.NNE84$](L
  2296. XM>@"9+RR`6DZZZ4I03R\M``@O+(!:3KKI/%!/2'H`ER\L@%I.NNDN4$]@&OZHS
  2297. XM_L3_:/^HL+P````$9`KC@#`[`.Q.^P``2JW_^&<*+RW_^$ZZZ<183R`M__Q.5
  2298. XM74YU.B``(&ES(&$@9&ER96-T;W)Y("AN;W0@<F5M;W9E9"D*`#H@8V]U;&0@;
  2299. XM;F]T(&%C8V5S<R!F:6QE(``*`#H@8V]U;&0@;F]T(&5X86UI;F4@9FEL92``6
  2300. XM"@``3E7__"\$>`!(;?_\+RT`"$ZZ[<)03V```,(O+0`,+RW__"\M``A.N@34B
  2301. XM3^\`#"@`8```NB\M``PO+?_\+RT`"$ZZ`/1/[P`,*`!@``"@2JR`$F8X2&R`W
  2302. XM(B\L@%I.NN@^4$](>@":+RR`6DZZZ#!03R\M``@O+(!:3KKH(E!/2'H`ER\LR
  2303. XM@%I.NN@44$]X`&!<2JR`$F8X2&R`(B\L@%I.NN?\4$](>@!S+RR`6DZZY^Y0#
  2304. XM3R\M``@O+(!:3KKGX%!/2'H`<2\L@%I.NN?24$]X`&`:_S#_2O]D_Z:PO```\
  2305. XM``1D"N.`,#L`[$[[```O+?_\3KKH;%A/(`0H'TY=3G4Z(&-O=6QD(&YO="!A+
  2306. XM8V-E<W,@9FEL92``"@`Z(&-O=6QD(&YO="!E>&%M:6YE(&9I;&4@``H``$Y5Q
  2307. XM_]I(YP\P>`$O+0`0+RT`"$ZZZU)03RP`L+S_____9@IP`$S?#/!.74YU2&W_Q
  2308. XM_"\M`!!.NNQH4$\J`$J&9T)*K(`"9SRZO`````)F&D*G+RT`$"\M``PO+0`(Z
  2309. XM3KH'@D_O`!`H`&`6+RT`$"\M``PO+0`(3KH%?$_O``PH`&```MI*K(`"9A!*D
  2310. XMK(`&9P`"CDJL@`YG``*&3KKGJBM`_^Y.NN>B*T#_ZDZZYR`K0/_F2JW_YF<,@
  2311. XM2JW_[F<&2JW_ZF8&>/]@``(V(&W_ZD(0+RT`$"\M_^I.NA784$^ZO`````)G8
  2312. XM4B\M_^I.NA):6$\D0"`*9RP@;?_JT<H;:/____MG'@PM`#K_^V<6#"T`+__[P
  2313. XM9PY(>@)6+RW_ZDZZ%9103R\M``A.NN8.6$\O`"\M_^I.NA5^4$](>/_^+RW_Q
  2314. XMZDZZ&+903RM`__)F``#P2JR`%F<``((@;?_N0A!(;(`B+RR`6DZZY@)03TAZN
  2315. XM`@(O+(!:3KKE]%!/+RW_ZB\L@%I.NN7F4$](>@'Z+RR`6DZZY=A03TAX`0`OK
  2316. XM+?_N+RR`7DZZ&(9/[P`,(&W_[@P0`'EG)"!M_^X,$`!99QHO+?_F3KKF:%A/+
  2317. XM+RW__$ZZYEY83W``8`#^4B\M_^I.NA>X6$\K0/_R9D1*K(`29CA(;(`B+RR`*
  2318. XM6DZZY7)03TAZ`8DO+(!:3KKE9%!/+RW_ZB\L@%I.NN564$](>@&++RR`6DZZP
  2319. XMY4A03W``8`#]_B\M_^H@;0`,2&@`A$ZZ"[)03R\M__).NA@F6$](>/_^+RT`@
  2320. XM"$ZZ%ZA03RM`__8O+?_F+RW_]DZZ%VI03RX`+RW_YB\M__9.NA=L4$]*@&=Z=
  2321. XM2H1O=B!M_^Y"$"\M``@O+?_N3KH4)%!/+RW_[DZZ$*Y83R1`(`IG+"!M_^[1M
  2322. XMRAMH____^V<>#"T`.O_[9Q8,+0`O__MG#DAZ`.,O+?_N3KH3Z%!/(&W_YE"(E
  2323. XM+P@O+?_N3KH3UE!/+RW_ZB\M_^Y.NOOB4$\H`&``_W8O+?_V3KH7;EA/+RW__
  2324. XMYDZZY2983R\M_^Y.NN646$\O+?_J3KKEBEA/8#Y*K(`29CA(;(`B+RR`6DZZ+
  2325. XMY#I03TAZ`',O+(!:3KKD+%!/+RT`""\L@%I.NN0>4$](>@!:+RR`6DZZY!!0]
  2326. XM3R\M__Q.NN3(6$\@!&``_+PO`#H@8W)E871E(&1I<F5C=&]R>2``/R``.B!U]
  2327. XM;F%B;&4@=&\@8W)E871E(&1I<F5C=&]R>2``"@`O`#H@`"!I<R!A(&1I<F5CE
  2328. XM=&]R>2`H;F]T(&-O<&EE9"D*`$Y5__@O!'@`3KKD="M`__A*K?_X9@AP_R@?'
  2329. XM3EU.=4AM__PO+0`03KKHL%!/8``!;B\M__PO+0`0+RT`#"\M``A.N@/83^\`(
  2330. XM$"@`8``!8B\M`!`O+0`,+RT`"$ZZ`=!/[P`,*`!@``%(2JR`%F=L(&W_^$(0<
  2331. XM2&R`(B\L@%I.NN,B4$](>@%$+RR`6DZZXQ103R\M`!`O+(!:3KKC!E!/2'H!%
  2332. XM/"\L@%I.NN+X4$](>`$`+RW_^"\L@%Y.NA6F3^\`#"!M__@,$`!Y9Q`@;?_X@
  2333. XM#!``66<&>`!@``#6+RT`$$ZZ%.Q83RE`@%)*K(!29D)*K(`29CA(;(`B+RR`M
  2334. XM6DZZXJ)03TAZ`-LO+(!:3KKBE%!/+RT`$"\L@%I.NN*&4$](>@#I+RR`6DZZ,
  2335. XMXGA03W@`8"`O+(!23KH5:EA/+RT`$"\M``PO+0`(3KH`Y$_O``PH`&!<2JR`4
  2336. XM$F8X2&R`(B\L@%I.NN(^4$](>@"C+RR`6DZZXC!03R\M`!`O+(!:3KKB(E!/A
  2337. XM2'H`IB\L@%I.NN(44$]X`&`:_H3^HOZ\_Z:PO`````1D"N.`,#L`[$[[```O]
  2338. XM+?_\3KKBKEA/+RW_^$ZZXQQ83R`$8`#^4CH@8W)E871E(&1I<F5C=&]R>2``?
  2339. XM/R``.B!C;W5L9"!N;W0@8W)E871E(&1E<W1I;F%T:6]N(&1I<F5C=&]R>2``L
  2340. XM"@`Z(&-O=6QD(&YO="!E>&%M:6YE(&1I<F5C=&]R>2``"@!.5?_X2.<.`$ZZQ
  2341. XMXD@K0/_\>@`O+0`03KH-.EA/+`!*K?_\9@IP_TS?`'!.74YU(&W__$(0+RT`H
  2342. XM$"\M__Q.NA"`4$]*AF<F(&W__-'&&"C__V<:N#P`.F<4N#P`+V<.2'H!0"\MY
  2343. XM__Q.NA!64$\O+0`(3KK@T%A/+P`O+?_\3KH00%!/2&W_^"\M__Q.NN8@4$]@8
  2344. XM``#B+RW_^"\M__PO+0`,+RT`"$ZZ`4A/[P`0*@!@``#62JR`$F942&R`(B\L*
  2345. XM@%I.NN"R4$](>@#:+RR`6DZZX*103R\M``@O+(!:3KK@EE!/2'H`U2\L@%I.?
  2346. XMNN"(4$\O+?_\+RR`6DZZX'I03TAZ`,HO+(!:3KK@;%!/>@!@=D*G+RW__"\MN
  2347. XM``PO+0`(3KH`SD_O`!`J`&!<2JR`$F8X2&R`(B\L@%I.NN`Z4$](>@",+RR`5
  2348. XM6DZZX"Q03R\M__PO+(!:3KK@'E!/2'H`CR\L@%I.NN`04$]Z`&`:_Q#_+O^,6
  2349. XM_Z:PO`````1D"N.`,#L`[$[[```O+?_X3KK@JEA/+RW__$ZZX1A83R`%8`#^4
  2350. XMB"\`.B!C;W5L9"!N;W0@;6]V92!F:6QE(``@;VYT;R!D:7)E8W1O<GD@``H`/
  2351. XM.B!S;VUE=&AI;F<@:7,@87=R>2!W:71H(&9I;&4@``H``$Y5__Q(YPX`>`!Z:
  2352. XM`"\M`!`O+0`(3KKC<%!/+`"PO/____]F%"\M__Q.NN"66$]P`$S?`'!.74YU-
  2353. XM3KK@*BM`__QF!'#_8.I*K0`49P`!0$J&9V8@;0`,(FT`%"`0L)%F6$JL@`)FT
  2354. XM3DJL@!)F.$AL@"(O+(!:3KK?$%!/2'H!3B\L@%I.NM\"4$\O+0`(+RR`6DZZ$
  2355. XMWO103TAZ`4$O+(!:3KK>YE!/+RW__$ZZX!983W`!8`#_?F```-9*K(`69P``(
  2356. XMI"!M__Q"$$AL@"(O+(!:3KK>ME!/2'H!$"\L@%I.NMZH4$\O+0`0+RR`6DZZB
  2357. XMWII03TAZ`0$O+(!:3KK>C%!/2'@!`"\M__PO+(!>3KH1.D_O``P@;?_\#!``S
  2358. XM>6<:(&W__`P0`%EG$"\M__Q.NM^46$]P`6``_OQ"ITAX``$O+0`03KKO3$_O)
  2359. XM``RPO/____]F$"\M__Q.NM]J6$]P`&``_M)@*D*G+RR`$B\M`!!.NN\@3^\`Z
  2360. XM#+"\_____V80+RW__$ZZWSY83W``8`#^IDJ&9Q9*K(`"9Q`O+0`0+RT`"$ZZ5
  2361. XM`\103V`2+RT`$"\M``PO+0`(84)/[P`,*``O+?_\3KK?`%A/(`1@`/YH.B!CQ
  2362. XM86YN;W0@8V]P>2``('1O(&ET<V5L9B$*`#H@;W9E<G=R:71E(``_(`!.5?_X*
  2363. XM2.<,($ZZW:HJ`%F%NKP```"`;"Q*K(`29AQ(;(`B+RR`6DZZW6A03TAZ`J0O8
  2364. XM+(!:3KK=6E!/</],WP0P3EU.=2!M``P@*`!\4("PA6\$(`5@"B!M``P@*`!\A
  2365. XM4(`J`$AY``$``2\%3KH08E!/)$!*@&9$<@0@!4ZZ#*HJ`$AY``$``2\%3KH0T
  2366. XM1%!/)$!*@&8F2JR`$F8<2&R`(B\L@%I.NMSL4$](>@(Z+RR`6DZZW-Y03W#_D
  2367. XM8()(>`/N+RT`$$ZZ#VY03RM`__AF3DJL@!)F.$AL@"(O+(!:3KK<LE!/2'H"C
  2368. XM$B\L@%I.NMRD4$\O+0`0+RR`6DZZW)903TAZ`@HO+(!:3KK<B%!/+P4O"DZZK
  2369. XM#^I03W``8`#_(DAX`^TO+0`(3KH/#%!/*T#__&982JR`$F8X2&R`(B\L@%I."
  2370. XMNMQ04$](>@'&+RR`6DZZW$)03R\M``@O+(!:3KK<-%!/2'H!OB\L@%I.NMPF8
  2371. XM4$\O+?_X3KH..%A/+P4O"DZZ#WY03W``8`#^MB\%+PHO+?_\3KH.OD_O``PH6
  2372. XM`$J`;WXO!"\*+RW_^$ZZ#OA/[P`,L+S_____9F)*K(`29CA(;(`B+RR`6DZZW
  2373. XMV\I03TAZ`58O+(!:3KK;O%!/+RT`$"\L@%I.NMNN4$](>@%3+RR`6DZZVZ!0_
  2374. XM3R\M__Q.N@VR6$\O+?_X3KH-J%A/+P4O"DZZ#NY03W#_8`#^)F``_VXO+?_\R
  2375. XM3KH-BEA/+RW_^$ZZ#8!83[B\_____V9.2JR`$F8X2&R`(B\L@%I.NMM(4$](\
  2376. XM>@$"+RR`6DZZVSI03R\M``@O+(!:3KK;+%!/2'H!`2\L@%I.NML>4$\O!2\*[
  2377. XM3KH.@%!/<`!@`/VX2JR`&F=`(&T`#"\H`'0O+0`03KH-Z%!/(&T`#$AH`)`OE
  2378. XM+0`03KH-R%!/+RT`$"!M``Q(:`"$3KH!5%!/+P4O"DZZ#C103W`"8`#];#H@9
  2379. XM3W5T(&]F(&UE;6]R>2$*`#H@3W5T(&]F(&UE;6]R>2$*`#H@8V%N;F]T($]PX
  2380. XM96X@9FEL92``"@`Z(&-A;FYO="!/<&5N(&9I;&4@``H`.B!E<G)O<B!W<FET@
  2381. XM:6YG('1O(&9I;&4@`"X@1&ES:R!M87D@8F4@9G5L;"X*`#H@97)R;W(@<F5AO
  2382. XM9&EN9R!F<F]M(&9I;&4@``H``$Y5```O!"\M``PO+0`(3KH,Y%!/2H!G!'`!_
  2383. XM8`)P`"@`2H1F6DJL@!)F5$AL@"(O+(!:3KK9[E!/2'H`3"\L@%I.NMG@4$\O5
  2384. XM+0`(+RR`6DZZV=)03TAZ`$<O+(!:3KK9Q%!/+RT`#"\L@%I.NMFV4$](>@`P#
  2385. XM+RR`6DZZV:A03R`$*!].74YU.B!C;W5L9"!N;W0@;6]V92!F:6QE(``@=&\@R
  2386. XM``H`3E7_]$CG##`O+0`,3KH+R%A/*T#__&8*<`!,WPPP3EU.=4AX__XO+0`,U
  2387. XM3KH+XE!/)D!*@&8$<`!@X$ZZV:8J`$J%9P``E"\%+PM.N@N64$]*@&=Z+PM."
  2388. XMN@O:6$\H`"\+3KH,'%A/2'D``0`!2'@!`$ZZ#$I03R1`($50B"\(($I2B"\(3
  2389. XM3KH$QE!/($50B"\(3KH$REA/%(`O+0`((`KDB"\`+P1"ITAX`"(O+?_\3KH%!
  2390. XM"$_O`!@K0/_T2'@!`"\*3KH,*%!/+P1.N@NT6$\O!4ZZV6Y83V`(+PM.N@NBS
  2391. XM6$]@`/\X3E4``$CG"#!X`$AX__XO+0`(3KH+%E!/)$!*@&8*<`!,WPP03EU.W
  2392. XM=4ZZV-0F0"`+9R@O"R\*3KH*QE!/2H!G#B@K`'0O"TZZV1183V`,+PM.NMD*@
  2393. XM6$]P`F#&+PI.N@L\6$\(!```9@1P`6`"<`!(P&"N("\`!"QL@&).[OZJ(F\`_
  2394. XM!"QL@&).[OZD3.\!`0`$0^\`#"QL@&).[O\6(&\`!$/O``@L;(!B3N[_'"!O3
  2395. XM``0@+P`(+&R`8D[N_LXB;P`$+&R`8D[N_L@O"DSO!P$`""QL@&).KOZ\)%].S
  2396. XM=4SO`P$`!"QL@&).[O["(&\`!"QL@&).[O[X3.\!`0`$(B\`#"QL@&).[OZVU
  2397. XM(&\`!"QL@&).[O\*(&\`!"QL@&).KO[^9@I![(""(+P````!3G4B;P`$+&R`#
  2398. XM8D[N_Q`O"B1O``@L;(!B3J[^DB1?3G5,[P,```0L;(!B3N[^L"!O``1,[P`#$
  2399. XM``@L;(!B3N[^GB!O``1,[P`#``@L;(!B3N[^F"`O``0L;(!B3N[^7")O``0LC
  2400. XM;(!B3N[^\DSO`@(`!"QL@&).[O[L2.<`,"!O``P@+P`03.\.```4+&R`8DZN)
  2401. XM_P1,WPP`3G5,[P,```0@+P`,+&R`8D[N_N9,[P,```0L;(!B3N[^X$SO``,`(
  2402. XM!"QL@&).[OXX3.\#```$+&R`8D[N_E!,[P$!``0L;(!B3N[^2B!O``0L;(!B"
  2403. XM3N[^1"!O``0L;(!B3N[^/DSO`P``!"QL@&).[OWV3.\#```$("\`#"QL@&).3
  2404. XM[OWP("\`!"QL@&).[OWJ(&\`!$SO``,`"")O`!`L;(!B3N[^5B!O``0L;(!B<
  2405. XM3N[^VDSO`P``!"QL@&).[O[43.\#```$3.\``P`,+&R`8D[N_@(@;P`$("\`"
  2406. XM""QL@&).[OW\(F\`!"QL@&).[OX(+&R`8D[N_C),[P`%``0L;(!B3N[^ABQL$
  2407. XM@&).[OXL(F\`!"QL@&).[OXF3.\``P`$+&R`8DZN_GI![("&((E.=4SO``8`'
  2408. XM!"QL@&).KOYT8.@B+P`$+&R`8DZN_FY@VDSO``8`!"QL@&).KOYH8,HL;(!BJ
  2409. XM3J[^&F?`,V\`!O_^(`E@MB`O``0L;(!B3J[^@&"H(&\`!"`O``@L;(!B3J[^,
  2410. XM8F"6+&R`8D[N_HPB;P`$+&R`8D[N_B`B;P`$+&R`8D[N_A0B;P`$+&R`8D[NI
  2411. XM_@Y,[P,```1,[P`#``PL;(!B3N[]Y"\*3.\'```(+&R`8DZN_=XD7TYU(B\`:
  2412. XM!"QL@&).[OW83.\#```$+&R`8D[N_=(@;P`$+&R`8D[N_<P@;P`$+&R`8D[NQ
  2413. XM_<8@;P`$+&R`8D[N_<!,[P$"``0L;(!B3N[]NB!O``0L;(!B3N[]M"(O``0LS
  2414. XM;(!B3N[]KDSO``,`!"QL@&).[OVH3.\``P`$+&R`8D[N_:),[P`#``0L;(!BE
  2415. XM3N[]G"`O``0L;(!B3N[]EDSO`P``!"QL@&).[OV0(&\`!"QL@&).[OV*(B\`7
  2416. XM!"QL@&).[OV$(&\`!"`((F\`"!#99OQ.=2!O``0@"$H89OR1P"`(4X!.=7``;
  2417. XM$"\`![`\`&!C"K`\`'IB!)`\`"!.=7``$"\`![`\`$!C"K`\`%IB!-`\`"!.O
  2418. XM=2!O``0@+P`($AAG"K(`9O@@"%.`3G5P`$YU3E7__$CG`#!"IT*G3KK[RB9`]
  2419. XM2H!03V8*<`!,WPP`3EU.=4AY``$``4AX`$1.N@;6)$!*@%!/9@PO"TZZ^ZQPQ
  2420. XM`%A/8-8@2M'\````%"5(``HE2@`4)4L`&"5M``P`'"5M`!``*"5M`!0`+"5M2
  2421. XM`!@`,"5M`!P`-"5M`"``."5M`"0`/"5M`"@`0"\*+RT`"$ZZ!N(O"TZZ!P0O)
  2422. XM"TZZ!JHK:@`@__Q(>`!$+PI.N@:&+PM.NOLV("W__$_O`!Q@`/]<87!#[(!2F
  2423. XM1>R`4K7)9@XR/``<:PAT`"+"4<G__"E/@&XL>``$*4Z`BDCG@(`(+@`$`2EGH
  2424. XM$$OZ``A.KO_B8`9"I_-?3G-#^@`@3J[^:"E`@(YF#"X\``.`!TZN_Y1@!$ZZS
  2425. XMT1!03TYU9&]S+FQI8G)A<GD`2?D``'_^3G5.50``2.<,,"1M`!`@;0`(2J@`D
  2426. XMK&<8(&T`""`H`*SE@"@`($0@*``0Y8`F0&`$)FR`2!`32(!(P-"M``Q4@"E`_
  2427. XM@))"IR\L@)).N@6$*4"`EE!/9@A,WPPP3EU.=1`32(!(P"H`+P4@2U*(+P@O6
  2428. XM+("63KH!CB!L@);1Q4/Z`5@0V6;\+RT`#"\*+RR`EDZZ`4X@;("60C!8`"E\L
  2429. XM`````8!^(&R`EM'%)DA2BR1+3^\`&!`32(!(P"H`L+P````@9R"ZO`````EG=
  2430. XM&+J\````#&<0NKP````-9PBZO`````IF!%*+8,P,$P`@;0``C`P3`")F,E*+D
  2431. XM($M2BQ`02(!(P"H`9R`@2E**$(6ZO````")F$`P3`")F!%*+8`9"*O__8`)@L
  2432. XMTF!$($M2BQ`02(!(P"H`9S"ZO````"!G*+J\````"6<@NKP````,9QBZO```1
  2433. XM``UG$+J\````"F<(($I2BA"%8,(@2E**0A!*A68"4XM2K(!^8`#_/$(20J<@1
  2434. XM+(!^4H#E@"\`3KH$2"E`@'I03V8(0JR`?F``_KYZ`"9L@)9@'B`%Y8`@;(!Z,
  2435. XM(8L(`"!+(`A*&&;\D<!3B%*(U\A2A;JL@'YMW"`%Y8`@;(!Z0K`(`&``_H(@^
  2436. XM`#`\?_]@!#`O``X@;P`$2AAF_%-((F\`"%-`$-E7R/_\9P)"$"`O``1.=4SOH
  2437. XM`P``!"`((B\`#&`"$-E7R?_\9P9206`"0AA1R?_\3G5(YT@`0H1*@&H$1(!21
  2438. XM1$J!:@9$@0I$``%A/DI$9P)$@$S?`!)*@$YU2.=(`$*$2H!J!$2`4D1*@6H"]
  2439. XM1(%A&B`!8-@O`6$2(`$B'TJ`3G4O`6$&(A]*@$YU2.<P`$A!2D%F($A!-@$T]
  2440. XM`$)`2$"`PR(`2$`R`H+#,`%"04A!3-\`#$YU2$$F`2(`0D%(04A`0D!T#]"`B
  2441. XMTX&V@6($DH-20%'*__),WP`,3G5.5?_\2'@0`$*G3KH#?"M`__P(```,4$]G\
  2442. XM$DJL@'9F""`M__Q.74YU3KK3+'``8/1.50``2JR`FF<&(&R`FDZ0+RT`"$ZZ]
  2443. XM``A83TY=3G5.5?_\+P0K;0`(__Q*K("B9RQX`&`*+P1.N@#\6$]2A#`L@$9(T
  2444. XMP+B`;>PP+(!&P?P`!B\`+RR`HDZZ`JI03TJL@)YG!B!L@)Y.D$JL@$QG"B\L,
  2445. XM@$Q.N@(>6$]*K("F9P@@;("F(*R`JDJL@*YG"B\L@*Y.N@(R6$]*K("R9PHO7
  2446. XM+("R3KH"(EA/2JR`MF<*+RR`MDZZ`A)83TJL@+IG"B\L@+I.N@("6$\L>``$S
  2447. XM""X`!`$I9Q0O#4OZ``I.KO_B*E]@!D*G\U].<TJL@+YF*DJL@)9G(B\L@)(OG
  2448. XM+("63KH"!B`L@'Y2@.6`+P`O+(!Z3KH!]$_O`!!@#DZZ`=XO+("^3KH"+%A/M
  2449. XM("W__"YL@&Y.=2@?3EU.=4Y5``!(YPX@*"T`"'(&(`1.N@!$)$#5[("B2H1M/
  2450. XM#C`L@$9(P+B`;`1*DF82*7P````"@,)P_TS?!'!.74YU,"H`!,!\@`!F""\2B
  2451. XM3KH`,EA/0I)P`&#@2.=P`#0!Q,`F`4A#QL!(0T)#U(-(0,#!2$!"0-""3-\`L
  2452. XM#DYU3OH``B(O``0L;(".3N[_W"(O``0L;(".3N[_B$[Z``(B+P`$+&R`CD[NL
  2453. XM_X).^@`"(B\`!"QL@(Y.[O^X(B\`!"QL@(Y.[O]23OH``DSO``8`!"QL@(Y.$
  2454. XM[O^:3.\`!@`$+&R`CD[N_Y1.^@`"+&R`CD[N_\I.^@`"3.\`!@`$+&R`CD[NG
  2455. XM_ZQ.^@`"3.\`!@`$+&R`CD[N_^(B+P`$+&R`CD[N_RY.^@`"3.\`#@`$+&R`0
  2456. XMCD[N_]9.^@`"3.\`!@`$+&R`CD[N_[),[P`&``0L;(".3N[_3$SO``8`!"QL0
  2457. XM@(Y.[O]&3OH``B(O``0L;(".3N[_ID[Z``),[P`.``0L;(".3N[_T"(O``0L^
  2458. XM;("*3N[_*$[Z``(B;P`$+&R`BD[N_F).^@`"3.\``P`$+&R`BD[N_SI.^@`"C
  2459. XM(F\`!"QL@(I.[O[:3OH``BQL@(I.[O]\3OH``B)O``0@+P`(+&R`BD[N_RY.]
  2460. XM^@`"(&\`!"QL@(I.[OZ,3OH``BQL@(HB;P`$("\`"$[N_=@L;("*3N[_=DSON
  2461. XM`P``!"QL@(I.[OZ2(F\`!"QL@(I.[OZ&3.\``P`$+&R`BD[N_LY.^@`"(&\`Q
  2462. XM!"QL@(I.[OZ```````/L`````0````$``"\(`````````_(```/J````%```^
  2463. XM``````````````````````````````````$`````````````````````````!
  2464. XM`````````````````````````````!0````````````````#\@```^L````!X
  2465. X$```#\@``U
  2466. X``
  2467. Xend
  2468. Xsize 13864
  2469. SHAR_EOF
  2470. echo "extracting mvtest.sh"
  2471. sed 's/^X//' << \SHAR_EOF > mvtest.sh
  2472. X#
  2473. X# Regression test script for mv/cp/rm
  2474. X#
  2475. X# Copyright 1989 Edwin Hoogerbeets
  2476. X#
  2477. X# This code may be freely redistributed as long as no charges other than
  2478. X# reasonable copying fees are levied for it.
  2479. X#
  2480. X# This script is for the Dillon/Drew shell. To see what the utilities
  2481. X# are doing, compile with -DDEBUG and then source this script for a
  2482. X# verbose listing of what's happening.
  2483. X#
  2484. X
  2485. X# create the test environment
  2486. Xecho mkdir foo
  2487. Xmkdir foo
  2488. Xecho cp * foo
  2489. Xcp * foo
  2490. X
  2491. X#
  2492. X# test mv on same volume
  2493. X#
  2494. X
  2495. X# mv directory to a new name
  2496. X# expected result: foo will be renamed to bar
  2497. Xecho mv foo bar
  2498. Xmv foo bar
  2499. X
  2500. X# mv directory to existing directory
  2501. X# expected result: bar will be renamed foo/bar
  2502. Xecho mkdir foo
  2503. Xmkdir foo
  2504. Xecho mv bar foo
  2505. Xmv bar foo
  2506. X
  2507. X# mv file to directory
  2508. X# expected result: rm will be renamed to foo
  2509. Xecho mv rm foo
  2510. Xmv rm foo
  2511. X
  2512. X# mv multiple files to directory
  2513. X# expected result: foo/rm and cp will be renamed to foobar/rm and foobar/cp
  2514. Xecho mv foo/rm cp foobar
  2515. Xmv foo/rm cp foobar
  2516. X
  2517. X# test "" as current directory
  2518. X# expected results: everything in the foobar directory will be renamed
  2519. X# under the current directory
  2520. Xecho foobar/* \"\"
  2521. Xmv foobar/* \"\"
  2522. X
  2523. X# mv multiple directories to directory
  2524. X# expected result: foo and foobar will be renamed to barfoo/foo
  2525. X# and barfoo/foobar
  2526. Xecho mkdir barfoo
  2527. Xmkdir barfoo
  2528. Xecho mv foo foobar barfoo
  2529. Xmv foo foobar barfoo
  2530. X
  2531. X# mv file to file
  2532. X# expected result: rm will be renamed to arm and back to rm
  2533. Xecho mv rm arm
  2534. Xmv rm arm
  2535. Xecho mv arm rm
  2536. Xmv arm rm
  2537. X
  2538. Xecho mv barfoo/foo \"\"
  2539. Xmv barfoo/foo \"\"
  2540. X
  2541. X#
  2542. X# test mv across volumes
  2543. X#
  2544. X
  2545. Xecho mkdir ram:foo
  2546. Xmkdir ram:foo
  2547. X
  2548. X# mv directory to existing directory
  2549. X# expected result: foo will get recursively moved to ram:foo
  2550. Xecho mv foo ram:
  2551. Xmv foo ram:
  2552. X
  2553. X# mv directory to a non-existant directory
  2554. X# expected result: ram:foo will get recursively moved to rad:foo
  2555. Xecho mv ram:foo rad:foo
  2556. Xmv ram:foo rad:foo
  2557. X
  2558. X# mv file to existing directory
  2559. X# expected result: rm will get moved to ram:rm
  2560. Xecho mv rm ram:
  2561. Xmv rm ram:
  2562. X
  2563. X# mv file to non-existant name
  2564. X# expected result:  ram:rm will be moved to arm and then to rm
  2565. Xecho mv ram:rm arm
  2566. Xmv ram:rm arm
  2567. Xecho mv arm rm
  2568. Xmv arm rm
  2569. X
  2570. X#
  2571. X# test cp
  2572. X#
  2573. X
  2574. X# create the test environment
  2575. Xecho mkdir foo
  2576. Xmkdir foo
  2577. Xecho cp * foo
  2578. Xcp * foo
  2579. Xecho cat "<nil: >bar"
  2580. Xcat <nil: >bar
  2581. X
  2582. X# copy a zero length file
  2583. Xecho cp bar booboo
  2584. Xcp bar booboo
  2585. Xecho rm bar booboo
  2586. Xrm bar booboo
  2587. X
  2588. X# copy directory to new directory
  2589. X# expected result: foo/* will be copied to be asdf/*
  2590. Xecho cp -r foo asdf
  2591. Xcp -r foo asdf
  2592. X
  2593. X# copy multiple directories to a directory
  2594. X# expected result: foo/* and asdf/* will be copied to fooasdf/foo/*
  2595. X# and to fooasdf/asdf/* respectively
  2596. Xecho cp -r foo asdf fooasdf
  2597. Xcp -r foo asdf fooasdf
  2598. X
  2599. X# copy directory to existing directory
  2600. X# expected result: barfoo/* will be copied to asdf/barfoo/*
  2601. Xecho cp -r barfoo asdf
  2602. Xcp -r barfoo asdf
  2603. X
  2604. X# copy files to directory
  2605. X# expected result: cp rm and mv will be copied to asdf/cp asdf/rm
  2606. X# and asdf/mv
  2607. Xecho cp rm cp mv asdf
  2608. Xcp rm cp mv asdf
  2609. X
  2610. X# test [lack of] -r option
  2611. X# expected result: complain about directories not being copied
  2612. Xecho cp * asdf
  2613. Xcp * asdf
  2614. X
  2615. X# cp across volumes (this test shouldn't matter)
  2616. X# expected result: * will be copied to ram:asdf/*
  2617. Xecho cp * ram:asdf
  2618. Xcp * ram:asdf
  2619. X
  2620. X#
  2621. X# test rm
  2622. X#
  2623. X
  2624. Xecho cd asdf
  2625. Xcd asdf
  2626. X
  2627. X# test [lack of] -r option
  2628. X# expected result: only files will be erased
  2629. Xecho rm *
  2630. Xrm *
  2631. X
  2632. X# test -r option
  2633. X# expected result: directories and all will be erased
  2634. Xecho rm -r *
  2635. Xrm -r *
  2636. X
  2637. Xecho cd /
  2638. Xcd /
  2639. X
  2640. X#
  2641. X# test -i option
  2642. X#
  2643. X
  2644. X# expected result: directory creation and clobbering files will be okayed
  2645. X# before proceding
  2646. Xecho mv -i rad:foo ram:foo
  2647. Xmv -i rad:foo ram:foo
  2648. X
  2649. X#
  2650. X# test delete protection and -f option
  2651. X#
  2652. X
  2653. X# set up
  2654. Xecho rm -r foo
  2655. Xrm -r foo
  2656. X
  2657. Xecho cp rm foo
  2658. Xcp rm foo
  2659. Xecho protect foo rwe
  2660. Xprotect foo rwe
  2661. X
  2662. X# test copying to a delete protected file
  2663. X# expected result: should ask for permission to overwrite foo
  2664. Xecho cp rm foo
  2665. Xcp rm foo
  2666. X
  2667. Xecho protect foo rwe
  2668. Xprotect foo rwe
  2669. X
  2670. X# test -f option on mv
  2671. X# expected result: rm will be renamed to foo despite delete protect
  2672. Xecho mv -f rm foo
  2673. Xmv -f rm foo
  2674. X
  2675. Xecho protect foo rwe
  2676. Xprotect foo rwe
  2677. X
  2678. X# test -f option on rm
  2679. X# expected result: foo will be deleted no problem
  2680. Xecho rm -f foo
  2681. Xrm -f foo
  2682. X
  2683. Xecho cp cp rm
  2684. Xcp cp rm
  2685. X
  2686. X#
  2687. X# test -  option
  2688. X#
  2689. X
  2690. X# set up
  2691. Xecho mkdir -d
  2692. Xmkdir -d
  2693. X
  2694. X# expected result: -d will be recursively removed
  2695. Xecho rm -r - -d
  2696. Xrm -r - -d
  2697. X
  2698. X#
  2699. X# test bad input
  2700. X#
  2701. X
  2702. X# move non-existant files
  2703. X# expected result: complain about no access to non-existant files
  2704. Xecho mv FidgeMeJerk Kawanga BoongaBoonga Maximillian
  2705. Xmv FidgeMeJerk Kawanga BoongaBoonga Maximillian
  2706. X
  2707. X# remove non-existant file
  2708. X# expected result: complain about could not remove non-existant files
  2709. Xecho rm foobarandgrill
  2710. Xrm foobarandgrill
  2711. X
  2712. X# copy or move to the same file
  2713. X# expected result: mv works but cp should complain about not being
  2714. X# able to copy a file to itself
  2715. Xecho mv cp Cp
  2716. Xmv cp Cp
  2717. Xecho cp mv mv
  2718. Xcp mv mv
  2719. X
  2720. X# no args
  2721. X# expected result: usage info displayed
  2722. Xecho cp
  2723. Xcp
  2724. X
  2725. X# no files
  2726. X# expected result: usage info displayed
  2727. Xecho cp -r
  2728. Xcp -r
  2729. X
  2730. X# bad options
  2731. X# expected result: complain about bad option and usage
  2732. Xecho cp -q
  2733. Xcp -q
  2734. X
  2735. X# not enough args
  2736. X# expected result: usage info displayed
  2737. Xecho mv foo
  2738. Xmv foo
  2739. X
  2740. X# move directory onto a file
  2741. X# expected result: complain and give usage
  2742. Xecho mv asdf rm
  2743. Xmv asdf rm
  2744. X
  2745. X#
  2746. X# Test wildcarding (needs to compiled with -DARP and linked with -la32)
  2747. X#
  2748. X
  2749. X# expected result: everything will get copied to the new directory asdf
  2750. Xecho cp "*" asdf
  2751. Xcp "*" asdf
  2752. X
  2753. X# expected result: everything will get copied to the new directory asdf
  2754. Xecho cp "#?" asdf
  2755. Xcp "#?" asdf
  2756. X
  2757. X# expected result: two letter file names will get copied to directory asdf
  2758. Xecho cp "??" asdf
  2759. Xcp "??" asdf
  2760. X
  2761. X#
  2762. X# cleanup
  2763. X#
  2764. X
  2765. Xecho rm -fr asdf barfoo ram:asdf ram:foo foo fooasdf Maximillian rad:bar
  2766. Xrm -fr asdf barfoo ram:asdf ram:foo foo fooasdf Maximillian rad:bar
  2767. X
  2768. X
  2769. X
  2770. SHAR_EOF
  2771. echo "End of archive 1 (of 1)"
  2772. # if you want to concatenate archives, remove anything after this line
  2773. exit
  2774.